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

This commit is contained in:
mgw
2024-08-20 11:27:34 +08:00
27 changed files with 689 additions and 290 deletions

View File

@@ -53,6 +53,23 @@ const tableRequiredList = [
] ]
patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', { patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', {
setup() {
owl.onMounted(() => {
try {
const dom = this.__owl__.bdom.el
const buttonsDom = $(dom).find('.o_form_status_indicator_buttons ')
if (buttonsDom) {
const dom1 = buttonsDom.children('.o_form_button_save')
const dom2 = buttonsDom.children('.o_form_button_cancel')
dom1.append('保存')
dom2.append('取消')
}
} catch (e) {
console.log(e)
}
});
},
// 你可以重写或者添加一些方法和属性 // 你可以重写或者添加一些方法和属性
async _onDiscardChanges() { async _onDiscardChanges() {
// var self = this; // var self = this;
@@ -183,17 +200,6 @@ patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', {
// }) // })
$(function () { $(function () {
document.addEventListener('click', function () {
const dom = $('.o_form_status_indicator_buttons ')
if (dom) {
const dom1 = dom.children().eq(0)
const dom2 = dom.children().eq(1)
if (!dom1.text()) {
dom1.append('保存')
dom2.append('取消')
}
}
})
function customRequired() { function customRequired() {
let timer = null let timer = null

View File

@@ -43,6 +43,7 @@
'sf_manufacturing/static/src/js/kanban_change.js', 'sf_manufacturing/static/src/js/kanban_change.js',
'sf_manufacturing/static/src/scss/kanban_change.scss', 'sf_manufacturing/static/src/scss/kanban_change.scss',
'sf_manufacturing/static/src/xml/button_show_on_tree.xml', 'sf_manufacturing/static/src/xml/button_show_on_tree.xml',
'sf_manufacturing/static/src/js/workpiece_delivery_wizard_confirm.js',
] ]
}, },

View File

@@ -388,7 +388,7 @@ class Manufacturing_Connect(http.Controller):
ret = json.loads(datas) ret = json.loads(datas)
request.env['center_control.interface.log'].sudo().create( request.env['center_control.interface.log'].sudo().create(
{'content': ret, 'name': 'AutoDeviceApi/LocationChange'}) {'content': ret, 'name': 'AutoDeviceApi/LocationChange'})
logging.info('LocationChange_ret===========:%s' % ret) logging.info('库位变更LocationChange_ret:%s' % ret)
RfidCode = ret['RfidCode'] RfidCode = ret['RfidCode']
ChangeType = ret['ChangeType'] ChangeType = ret['ChangeType']
OldDeciveId = ret['OldDeciveId'] OldDeciveId = ret['OldDeciveId']
@@ -398,34 +398,79 @@ class Manufacturing_Connect(http.Controller):
OldDeciveStart = ret['OldDeciveStart'] OldDeciveStart = ret['OldDeciveStart']
OldDeciveEnd = ret['OldDeciveEnd'] OldDeciveEnd = ret['OldDeciveEnd']
temp_val_sn_id = None if ChangeType == 'Part':
old_localtion = None temp_val_sn_id = None
# if ChangeType == 'Part' or ChangeType == 'Tool': old_localtion = None
stock_lot_obj = request.env['stock.lot'].sudo().search( # if ChangeType == 'Part' or ChangeType == 'Tool':
[('rfid', '=', RfidCode)], limit=1) stock_lot_obj = request.env['stock.lot'].sudo().search(
logging.info('stock_lot_obj===========:%s' % stock_lot_obj) [('rfid', '=', RfidCode)], limit=1)
if not stock_lot_obj: logging.info('stock_lot_obj===========:%s' % stock_lot_obj)
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'} if not stock_lot_obj:
return json.JSONEncoder().encode(res) res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'}
if OldPosition: return json.JSONEncoder().encode(res)
old_localtion = request.env['sf.shelf.location'].sudo().search( if OldPosition:
[('barcode', '=', OldPosition)], limit=1) old_localtion = request.env['sf.shelf.location'].sudo().search(
logging.info('old_localtion===========:%s' % old_localtion) [('barcode', '=', OldPosition)], limit=1)
new_localtion = request.env['sf.shelf.location'].sudo().search( logging.info('old_localtion===========:%s' % old_localtion)
[('barcode', '=', NewPosition)], limit=1) new_localtion = request.env['sf.shelf.location'].sudo().search(
logging.info('new_localtion===========:%s' % new_localtion) [('barcode', '=', NewPosition)], limit=1)
if not new_localtion: logging.info('new_localtion===========:%s' % new_localtion)
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'} if not new_localtion:
return json.JSONEncoder().encode(res) res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'}
if old_localtion: return json.JSONEncoder().encode(res)
temp_val_sn_id = old_localtion.product_sn_id if old_localtion:
logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id) temp_val_sn_id = old_localtion.product_sn_id
old_localtion.product_sn_id = None logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id)
new_localtion.product_sn_id = temp_val_sn_id old_localtion.product_sn_id = None
logging.info('====1======') new_localtion.product_sn_id = temp_val_sn_id
else: logging.info('====1======')
new_localtion.product_sn_id = stock_lot_obj.id else:
logging.info('=====2======') new_localtion.product_sn_id = stock_lot_obj.id
logging.info('=====2======')
elif ChangeType == 'Tool':
# 对功能刀具库位变更信息进行更改
def write_tool(DeciveId):
if 'Tool' in DeciveId:
shelfinfo = list(filter(lambda x: x.get('DeviceId') == DeciveId,
request.env['sf.shelf.location'].sudo().get_sf_shelf_location_info(
DeciveId)))
total_data = request.env['sf.shelf.location.datasync'].sudo().get_total_data()
for item in shelfinfo:
shelf_barcode = request.env['sf.shelf.location.datasync'].sudo().find_our_code(
total_data, item['Postion'])
location_id = request.env['sf.shelf.location'].sudo().search(
[('barcode', '=', shelf_barcode)],
limit=1)
if location_id:
# 如果是线边刀库信息,则对功能刀具移动生成记录
if 'Tool' in item['Postion']:
tool = request.env['sf.functional.cutting.tool.entity'].sudo().search(
[('rfid', '=', item['RfidCode']), ('functional_tool_status', '!=', '已拆除')])
tool.sudo().tool_in_out_stock_location(location_id)
if tool:
location_id.product_sn_id = tool.barcode_id.id
# 修改功能刀具状态
tool_state = {'Nomal': '正常', 'Warning': '报警'}
if tool_state.get(item.get('State')):
if tool_state.get(item.get('State')) != tool.functional_tool_status:
tool.write({
'functional_tool_status': tool_state.get(item['State'])
})
else:
location_id.product_sn_id = False
logging.info('货架已获取信息:%s' % item)
else:
equipment_id = request.env['maintenance.equipment'].sudo().search([('name', '=', DeciveId)])
if equipment_id:
equipment_id.sudo().register_equipment_tool()
else:
res_1 = {'Succeed': False, 'ErrorCode': 202, 'Error': f'设备【{DeciveId}】不存在'}
return json.JSONEncoder().encode(res_1)
if OldDeciveId:
write_tool(OldDeciveId)
elif NewDeciveId:
write_tool(NewDeciveId)
except Exception as e: except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e} res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('LocationChange error:%s' % e) logging.info('LocationChange error:%s' % e)
@@ -458,7 +503,7 @@ class Manufacturing_Connect(http.Controller):
if f'RfidCode{i}' in ret: if f'RfidCode{i}' in ret:
rfid_code = ret[f'RfidCode{i}'] rfid_code = ret[f'RfidCode{i}']
logging.info('RfidCode:%s' % rfid_code) logging.info('RfidCode:%s' % rfid_code)
if rfid_code is not None: if rfid_code is not None and rfid_code != '':
rfid_codes.append(rfid_code) rfid_codes.append(rfid_code)
domain = [ domain = [
('rfid_code', '=', rfid_code), ('rfid_code', '=', rfid_code),
@@ -531,7 +576,7 @@ class Manufacturing_Connect(http.Controller):
if f'RfidCode{i}' in ret: if f'RfidCode{i}' in ret:
rfid_code = ret[f'RfidCode{i}'] rfid_code = ret[f'RfidCode{i}']
logging.info('RfidCode:%s' % rfid_code) logging.info('RfidCode:%s' % rfid_code)
if rfid_code is not None: if rfid_code is not None and rfid_code != '':
domain = [ domain = [
('rfid_code', '=', rfid_code), ('rfid_code', '=', rfid_code),
('routing_type', '=', 'CNC加工'), ('state', '!=', 'rework') ('routing_type', '=', 'CNC加工'), ('state', '!=', 'rework')

View File

@@ -6,6 +6,9 @@
<field name="code">sf.agv.scheduling</field> <field name="code">sf.agv.scheduling</field>
<field name="prefix">B%(year)s%(month)s%(day)s</field> <field name="prefix">B%(year)s%(month)s%(day)s</field>
<field name="padding">4</field> <field name="padding">4</field>
<field name="number_next">1</field>
<field name="implementation">standard</field>
<field name="use_date_range">True</field>
<field name="company_id" eval="False"/> <field name="company_id" eval="False"/>
</record> </record>
</data> </data>

View File

@@ -50,6 +50,21 @@ class AgvScheduling(models.Model):
delivery_workpieces = fields.Char('配送工件', compute=_compute_delivery_workpieces) delivery_workpieces = fields.Char('配送工件', compute=_compute_delivery_workpieces)
@api.model
def web_search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, count_limit=None):
domain = domain or []
new_domain = []
for index, item in enumerate(domain):
if isinstance(item, list):
if item[0] == 'delivery_workpieces':
new_domain.append('&')
new_domain.append(['workorder_ids.production_id.name', item[1], item[2]])
new_domain.append(['agv_route_type', '!=', '运送空料架'])
continue
new_domain.append(item)
return super(AgvScheduling, self).web_search_read(new_domain, fields, limit=limit, offset=offset)
@api.depends('task_completion_time', 'task_delivery_time') @api.depends('task_completion_time', 'task_delivery_time')
def _compute_task_duration(self): def _compute_task_duration(self):
for rec in self: for rec in self:
@@ -73,6 +88,7 @@ class AgvScheduling(models.Model):
agv_route_type: AGV任务类型 agv_route_type: AGV任务类型
workorders: 工单 workorders: 工单
""" """
_logger.info('创建AGV调度任务\r\n起点为【%s】,任务类型为【%s】,工单为【%s' % (agv_start_site_name, agv_route_type, workorders))
if not workorders: if not workorders:
raise UserError(_('工单不能为空')) raise UserError(_('工单不能为空'))
agv_start_site = self.env['sf.agv.site'].sudo().search([('name', '=', agv_start_site_name)], limit=1) agv_start_site = self.env['sf.agv.site'].sudo().search([('name', '=', agv_start_site_name)], limit=1)

View File

@@ -151,6 +151,11 @@ access_sf_production_wizard_group_sf_order_user,sf_production_wizard_group_sf_or
access_sf_processing_panel_group_plan_dispatch,sf_processing_panel_group_plan_dispatch,model_sf_processing_panel,sf_base.group_plan_dispatch,1,1,1,0 access_sf_processing_panel_group_plan_dispatch,sf_processing_panel_group_plan_dispatch,model_sf_processing_panel,sf_base.group_plan_dispatch,1,1,1,0
access_sf_agv_scheduling_admin,sf_agv_scheduling_admin,model_sf_agv_scheduling,base.group_system,1,1,1,1 access_sf_agv_scheduling_admin,sf_agv_scheduling_admin,model_sf_agv_scheduling,base.group_system,1,1,1,1
access_sf_agv_scheduling_group_sf_order_user,sf_agv_scheduling_group_sf_order_user,model_sf_agv_scheduling,sf_base.group_sf_order_user,1,1,1,0
access_sf_agv_scheduling_group_sf_mrp_manager,sf_agv_scheduling_group_sf_mrp_manager,model_sf_agv_scheduling,sf_base.group_sf_mrp_manager,1,1,1,0
access_sf_agv_scheduling_group_sf_equipment_user,sf_agv_scheduling_group_sf_equipment_user,model_sf_agv_scheduling,sf_base.group_sf_equipment_user,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
151
152
153
154
155
156
157
158
159
160
161

View File

@@ -0,0 +1,53 @@
odoo.define('sf_manufacturing.action_dispatch_confirm', function (require) {
const core = require('web.core');
const ajax = require('web.ajax');
const Dialog = require('web.Dialog');
var rpc = require('web.rpc');
var _t = core._t;
async function dispatch_confirm(parent, {params}) {
console.log(params, 'params')
console.log("<div>本次下发的工件数量为:" + params.workorder_count + ",是否确认?</div>", 'content')
const dialog = new Dialog(parent, {
title: "确认",
$content: $('<div>').append("请确认是否仅配送" + params.workorder_count + "个工件?"),
buttons: [
{ text: "确认", classes: 'btn-primary', close: true, click: () => dispatchConfirmed(parent, params) },
{ text: "取消", close: true },
],
});
dialog.open();
async function dispatchConfirmed(parent, params) {
console.log(parent, 'parent')
rpc.query({
model: 'sf.workpiece.delivery.wizard',
method: 'confirm',
args: [params.active_id]
,
kwargs: {
context: params.context,
}
}).then(res => {
console.log(res, 'res')
console.log(res.name, 'res')
parent.services.action.doAction({
'type': 'ir.actions.client',
'tag': 'display_notification',
'target': 'new',
'params': {
'message': '任务下发成功AGV任务调度编号为【' + res.name + '】',
'type': 'success',
'sticky': false,
'next': {'type': 'ir.actions.act_window_close'},
}
});
})
}
}
core.action_registry.add('dispatch_confirm', dispatch_confirm);
return dispatch_confirm;
});

View File

@@ -37,10 +37,34 @@
</field> </field>
</record> </record>
<record id="view_agv_scheduling_search" model="ir.ui.view">
<field name="name">sf.agv.scheduling.search</field>
<field name="model">sf.agv.scheduling</field>
<field name="arch" type="xml">
<search string="AGV调度">
<field name="name"/>
<field name="agv_route_name"/>
<field name="start_site_id"/>
<field name="end_site_id"/>
<field name="delivery_workpieces"/>
<field name="state" string="状态"/>
<filter name="filter_to_be_issued" string="待下发" domain="[('state', 'in', ['待下发'])]"/>
<filter name="filter_delivering" string="配送中" domain="[('state', 'in', ['配送中'])]"/>
<filter name="filter_delivered" string="已配送" domain="[('state', 'in', ['已配送'])]"/>
</search>
</field>
</record>
<record id="action_agv_scheduling_tree" model="ir.actions.act_window"> <record id="action_agv_scheduling_tree" model="ir.actions.act_window">
<field name="name">AGV调度</field> <field name="name">AGV调度</field>
<field name="res_model">sf.agv.scheduling</field> <field name="res_model">sf.agv.scheduling</field>
<field name="view_mode">tree</field> <field name="view_mode">tree</field>
<field name="context">
{
"search_default_filter_to_be_issued": 1,
"search_default_filter_delivering": 1,
}
</field>
</record> </record>
<menuitem <menuitem
@@ -49,6 +73,7 @@
sequence="28" sequence="28"
action="action_agv_scheduling_tree" action="action_agv_scheduling_tree"
parent="mrp.menu_mrp_manufacturing" parent="mrp.menu_mrp_manufacturing"
groups="sf_base.group_sf_order_user,sf_base.group_sf_mrp_manager,sf_base.group_sf_equipment_user"
/> />
</data> </data>
</odoo> </odoo>

View File

@@ -844,5 +844,11 @@
<field name="view_mode">tree</field> <field name="view_mode">tree</field>
<field name="domain">[('type','in',['运送空料架']),('name','not ilike','WDO')]</field> <field name="domain">[('type','in',['运送空料架']),('name','not ilike','WDO')]</field>
</record> </record>
<menuitem id="mrp.menu_mrp_manufacturing"
name="Operations"
sequence="10"
parent="mrp.menu_mrp_root"
groups="sf_base.group_sf_order_user,sf_base.group_sf_mrp_manager,sf_base.group_sf_equipment_user"/>
</odoo> </odoo>

View File

@@ -18,8 +18,8 @@
<field name="workcenter_id" options="{'no_create': True}"/> <field name="workcenter_id" options="{'no_create': True}"/>
</group> </group>
<footer> <footer>
<button string="确认配送" name="confirm" type="object" class="oe_highlight" attrs="{'invisible': [('confirm_button', '!=', '确认配送')]}"/> <button string="确认配送" name="dispatch_confirm" type="object" class="oe_highlight o_wizard_confirm_button" attrs="{'invisible': [('confirm_button', '!=', '确认配送')]}"/>
<button string="确认解除" name="confirm" type="object" class="oe_highlight" attrs="{'invisible': [('confirm_button', '!=', '确认解除')]}"/> <button string="确认解除" name="dispatch_confirm" type="object" class="oe_highlight o_wizard_confirm_button" attrs="{'invisible': [('confirm_button', '!=', '确认解除')]}"/>
<button string="取消" class="btn btn-secondary" special="cancel"/> <button string="取消" class="btn btn-secondary" special="cancel"/>
<script> <script>
setTimeout(function(){ setTimeout(function(){

View File

@@ -1,9 +1,16 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Part of YiZuo. See LICENSE file for full copyright and licensing details. # Part of YiZuo. See LICENSE file for full copyright and licensing details.
import json
import logging import logging
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
from datetime import datetime from datetime import datetime, date
from odoo import models, api, fields, _ from odoo import models, api, fields
def convert_datetime(obj):
if isinstance(obj, (datetime, date)):
return obj.isoformat() # 将 datetime 或 date 对象转换为 ISO 8601 字符串格式
raise TypeError(f"Type {type(obj)} not serializable")
class WorkpieceDeliveryWizard(models.TransientModel): class WorkpieceDeliveryWizard(models.TransientModel):
@@ -34,18 +41,18 @@ class WorkpieceDeliveryWizard(models.TransientModel):
self.workcenter_id = workcenter_ids[0] self.workcenter_id = workcenter_ids[0]
return { return {
'domain': 'domain':
{ {
'feeder_station_start_id': [('id', 'in', start_site_ids)], 'feeder_station_start_id': [('id', 'in', start_site_ids)],
'workcenter_id': [('id', 'in', workcenter_ids)], 'workcenter_id': [('id', 'in', workcenter_ids)],
} }
} }
else: else:
return { return {
'domain': 'domain':
{ {
'feeder_station_start_id': [], 'feeder_station_start_id': [],
'workcenter_id': [], 'workcenter_id': [],
} }
} }
def _get_agv_route_type_selection(self): def _get_agv_route_type_selection(self):
@@ -53,6 +60,31 @@ class WorkpieceDeliveryWizard(models.TransientModel):
delivery_type = fields.Selection(selection=_get_agv_route_type_selection, string='类型') delivery_type = fields.Selection(selection=_get_agv_route_type_selection, string='类型')
def dispatch_confirm(self):
if len(self.workorder_ids) < 4:
return {
'type': 'ir.actions.client',
'tag': 'dispatch_confirm',
'params': {
'workorder_count': len(self.workorder_ids),
'active_id': self.id,
'context': self.env.context
}
}
else:
scheduling = self.confirm()
# 显示通知
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'target': 'new',
'params': {
'message': '任务下发成功AGV任务调度编号为【%s' % scheduling['name'],
'type': 'success',
'sticky': False,
'next': {'type': 'ir.actions.act_window_close'},
}
}
def confirm(self): def confirm(self):
try: try:
# if self.workorder_id: # if self.workorder_id:
@@ -89,18 +121,7 @@ class WorkpieceDeliveryWizard(models.TransientModel):
item.button_start() item.button_start()
item.button_finish() item.button_finish()
# 显示通知 return scheduling.read()[0]
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'target': 'new',
'params': {
'message': '任务下发成功AGV任务调度编号为【%s' % scheduling.name,
'type': 'success',
'sticky': False,
'next': {'type': 'ir.actions.act_window_close'},
}
}
except Exception as e: except Exception as e:
logging.info('%s任务下发失败:%s' % (self.delivery_type, e)) logging.info('%s任务下发失败:%s' % (self.delivery_type, e))
raise UserError('%s任务下发失败:%s' % (self.delivery_type, e)) raise UserError('%s任务下发失败:%s' % (self.delivery_type, e))
@@ -167,7 +188,8 @@ class WorkpieceDeliveryWizard(models.TransientModel):
[('routing_type', '=', '解除装夹'), ('rfid_code', '=', barcode), [('routing_type', '=', '解除装夹'), ('rfid_code', '=', barcode),
('state', '=', 'ready')]) ('state', '=', 'ready')])
if workorder: if workorder:
if len(self.production_ids) > 0 and workorder.production_line_id.id != self.production_ids[0].production_line_id.id: if (len(self.production_ids) > 0 and
workorder.production_line_id.id != self.production_ids[0].production_line_id.id):
raise UserError('该rfid对应的制造订单号为%s的目的生产线不一致' % workorder.production_id.name) raise UserError('该rfid对应的制造订单号为%s的目的生产线不一致' % workorder.production_id.name)
# 将对象添加到对应的同模型且是多对多类型里 # 将对象添加到对应的同模型且是多对多类型里

View File

@@ -337,6 +337,7 @@
name="空料架配送" name="空料架配送"
sequence="11" sequence="11"
action="sf_manufacturing.sf_workpiece_delivery_empty_racks_act" action="sf_manufacturing.sf_workpiece_delivery_empty_racks_act"
groups="base.group_system"
parent="mrp.menu_mrp_manufacturing" parent="mrp.menu_mrp_manufacturing"
/> />
<!-- <menuitem --> <!-- <menuitem -->

View File

@@ -20,7 +20,8 @@
'views/sale_order_view.xml', 'views/sale_order_view.xml',
'views/res_partner_view.xml', 'views/res_partner_view.xml',
'views/purchase_order_view.xml', 'views/purchase_order_view.xml',
'views/quick_easy_order_view.xml' 'views/quick_easy_order_view.xml',
'views/purchase_menu.xml'
], ],
'assets': { 'assets': {
'web.assets_backend': [ 'web.assets_backend': [

View File

@@ -13,6 +13,11 @@ READONLY_FIELD_STATES = {
class ReSaleOrder(models.Model): class ReSaleOrder(models.Model):
_inherit = 'sale.order' _inherit = 'sale.order'
mrp_production_count = fields.Integer(
"Count of MO generated",
compute='_compute_mrp_production_ids',
groups='mrp.group_mrp_user,sf_base.group_sale_salemanager,sf_base.group_sale_director')
logistics_way = fields.Selection([('自提', '自提'), ('到付', '到付'), ('在线支付', '在线支付')], string='物流方式') logistics_way = fields.Selection([('自提', '自提'), ('到付', '到付'), ('在线支付', '在线支付')], string='物流方式')
state = fields.Selection( state = fields.Selection(
selection=[ selection=[

View File

@@ -96,5 +96,28 @@ access_product_supplierinfo_group_plan_director,product.supplierinfo user,produc
access_product_category_group_plan_director,product.category user,product.model_product_category,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
access_purchase_report_sf_base_group_purchase,purchase_report_sf_base_group_purchase,purchase.model_purchase_report,sf_base.group_purchase,1,0,0,0
access_purchase_report_sf_base_group_purchase_director,purchase_report_sf_base_group_purchase_director,purchase.model_purchase_report,sf_base.group_purchase_director,1,0,0,0
access_sale_order_sf_base_group_purchase,sale_order_sf_base_group_purchase,model_sale_order,sf_base.group_purchase,1,0,0,0
access_sale_order_sf_base_group_purchase_director,sale_order_sf_base_group_purchase_director,model_sale_order,sf_base.group_purchase_director,1,0,0,0
access_quality_check_group_sale_salemanager,quality_check_group_sale_salemanager,quality.model_quality_check,sf_base.group_sale_salemanager,1,0,0,0
access_quality_check_group_sale_director,quality_check_group_sale_director,quality.model_quality_check,sf_base.group_sale_director,1,0,0,0
access_stock_picking_group_sale_salemanager,stock_picking_group_sale_salemanager,stock.model_stock_picking,sf_base.group_sale_salemanager,1,0,0,0
access_stock_picking_group_sale_director,stock_picking_group_sale_director,stock.model_stock_picking,sf_base.group_sale_director,1,0,0,0
access_mrp_workorder_group_sale_salemanager,mrp_workorder_group_sale_salemanager,mrp.model_mrp_workorder,sf_base.group_sale_salemanager,1,0,0,0
access_mrp_workorder_group_sale_director,mrp_workorder_group_sale_director,mrp.model_mrp_workorder,sf_base.group_sale_director,1,0,0,0
access_mrp_unbuild_group_sale_salemanager,mrp_unbuild_group_sale_salemanager,mrp.model_mrp_unbuild,sf_base.group_sale_salemanager,1,0,0,0
access_mrp_unbuild_group_sale_director,mrp_unbuild_group_sale_director,mrp.model_mrp_unbuild,sf_base.group_sale_director,1,0,0,0
access_mrp_workcenter_productivity_group_sale_salemanager,mrp_workcenter_productivity_group_sale_salemanager,mrp.model_mrp_workcenter_productivity,sf_base.group_sale_salemanager,1,0,0,0
access_mrp_workcenter_productivity_group_sale_director,mrp_workcenter_productivity_group_sale_director,mrp.model_mrp_workcenter_productivity,sf_base.group_sale_director,1,0,0,0
access_sf_detection_result_group_sale_salemanager,sf_detection_result_group_sale_salemanager,sf_manufacturing.model_sf_detection_result,sf_base.group_sale_salemanager,1,0,0,0
access_sf_detection_result_group_sale_director,sf_detection_result_group_sale_director,sf_manufacturing.model_sf_detection_result,sf_base.group_sale_director,1,0,0,0
access_stock_scrap_group_sale_salemanager,stock_scrap_group_sale_salemanager,stock.model_stock_scrap,sf_base.group_sale_salemanager,1,0,0,0
access_stock_scrap_group_sale_director,stock_scrap_group_sale_director,stock.model_stock_scrap,sf_base.group_sale_director,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
96 access_purchase_report_sf_base_group_purchase_director purchase_report_sf_base_group_purchase_director purchase.model_purchase_report sf_base.group_purchase_director 1 0 0 0
97 access_sale_order_sf_base_group_purchase sale_order_sf_base_group_purchase model_sale_order sf_base.group_purchase 1 0 0 0
98 access_sale_order_sf_base_group_purchase_director sale_order_sf_base_group_purchase_director model_sale_order sf_base.group_purchase_director 1 0 0 0
99 access_quality_check_group_sale_salemanager quality_check_group_sale_salemanager quality.model_quality_check sf_base.group_sale_salemanager 1 0 0 0
100 access_quality_check_group_sale_director quality_check_group_sale_director quality.model_quality_check sf_base.group_sale_director 1 0 0 0
101 access_stock_picking_group_sale_salemanager stock_picking_group_sale_salemanager stock.model_stock_picking sf_base.group_sale_salemanager 1 0 0 0
102 access_stock_picking_group_sale_director stock_picking_group_sale_director stock.model_stock_picking sf_base.group_sale_director 1 0 0 0
103 access_mrp_workorder_group_sale_salemanager mrp_workorder_group_sale_salemanager mrp.model_mrp_workorder sf_base.group_sale_salemanager 1 0 0 0
104 access_mrp_workorder_group_sale_director mrp_workorder_group_sale_director mrp.model_mrp_workorder sf_base.group_sale_director 1 0 0 0
105 access_mrp_unbuild_group_sale_salemanager mrp_unbuild_group_sale_salemanager mrp.model_mrp_unbuild sf_base.group_sale_salemanager 1 0 0 0
106 access_mrp_unbuild_group_sale_director mrp_unbuild_group_sale_director mrp.model_mrp_unbuild sf_base.group_sale_director 1 0 0 0
107 access_mrp_workcenter_productivity_group_sale_salemanager mrp_workcenter_productivity_group_sale_salemanager mrp.model_mrp_workcenter_productivity sf_base.group_sale_salemanager 1 0 0 0
108 access_mrp_workcenter_productivity_group_sale_director mrp_workcenter_productivity_group_sale_director mrp.model_mrp_workcenter_productivity sf_base.group_sale_director 1 0 0 0
109 access_sf_detection_result_group_sale_salemanager sf_detection_result_group_sale_salemanager sf_manufacturing.model_sf_detection_result sf_base.group_sale_salemanager 1 0 0 0
110 access_sf_detection_result_group_sale_director sf_detection_result_group_sale_director sf_manufacturing.model_sf_detection_result sf_base.group_sale_director 1 0 0 0
111 access_stock_scrap_group_sale_salemanager stock_scrap_group_sale_salemanager stock.model_stock_scrap sf_base.group_sale_salemanager 1 0 0 0
112 access_stock_scrap_group_sale_director stock_scrap_group_sale_director stock.model_stock_scrap sf_base.group_sale_director 1 0 0 0
113
114
115
116
117
118
119
120
121
122
123

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- 采购-产品 -->
<menuitem id="purchase.menu_purchase_products" name="Products" parent="purchase.menu_purchase_root"
groups="sf_base.group_purchase_director,sf_base.group_purchase"
sequence="5"/>
<!-- 采购-产品-产品 -->
<menuitem id="purchase.menu_procurement_partner_contact_form" name="Products"
action="purchase.product_normal_action_puchased" parent="purchase.menu_purchase_products"
groups="sf_base.group_purchase_director,sf_base.group_purchase"
sequence="20"/>
<!-- 采购-报表 -->
<menuitem id="purchase.purchase_report_main" name="Reporting" parent="purchase.menu_purchase_root" sequence="99"
groups="purchase.group_purchase_manager,sf_base.group_purchase_director,sf_base.group_purchase"/>
<!-- 采购-报表-采购 -->
<menuitem id="purchase.purchase_report" name="Purchase" parent="purchase.purchase_report_main" sequence="99"
groups="purchase.group_purchase_manager,sf_base.group_purchase_director,sf_base.group_purchase"
action="purchase.action_purchase_order_report_all"/>
</odoo>

View File

@@ -86,6 +86,18 @@
</attribute> </attribute>
</xpath> </xpath>
<xpath expr="//form/sheet/div[@name='button_box']/button[@name='action_view_picking']"
position="replace">
<button type="object"
name="action_view_picking"
class="oe_stat_button"
icon="fa-truck" attrs="{'invisible':[('incoming_picking_count','=', 0)]}"
groups="stock.group_stock_user,sf_base.group_purchase,sf_base.group_purchase_director">
<field name="incoming_picking_count" widget="statinfo" string="收货"
help="Incoming Shipments"/>
</button>
</xpath>
<xpath expr="//field[@name='order_line']" position="attributes"> <xpath expr="//field[@name='order_line']" position="attributes">
<attribute name="attrs">{'readonly': [('state', 'in', ['purchase'])]} <attribute name="attrs">{'readonly': [('state', 'in', ['purchase'])]}
</attribute> </attribute>

View File

@@ -6,6 +6,13 @@
<field name="model">sale.order</field> <field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/> <field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//button[@name='action_view_delivery']" position="attributes">
<attribute name="groups">sf_base.group_sale_salemanager,sf_base.group_sale_director</attribute>
</xpath>
<xpath expr="//button[@name='action_view_mrp_production']" position="attributes">
<attribute name="groups">mrp.group_mrp_user,sf_base.group_sale_salemanager,sf_base.group_sale_director
</attribute>
</xpath>
<xpath expr="//field[@name='user_id']" position="replace"> <xpath expr="//field[@name='user_id']" position="replace">
<field name="user_id" widget="many2one_avatar_user" context="{'is_sale': True }"/> <field name="user_id" widget="many2one_avatar_user" context="{'is_sale': True }"/>
</xpath> </xpath>
@@ -35,12 +42,12 @@
<xpath expr="//form/header/button[@name='action_confirm'][2]" position="replace"> <xpath expr="//form/header/button[@name='action_confirm'][2]" position="replace">
<button name="action_confirm" data-hotkey="v" <button name="action_confirm" data-hotkey="v"
string="确认接单" type="object" context="{'validate_analytic': True}" string="确认接单" type="object" context="{'validate_analytic': True}"
attrs="{'invisible': ['|','&amp;',('check_status', '!=', 'approved'),('state', 'in', ['draft','cancel']),'&amp;','&amp;',('check_status', '=', 'approved'),('state', 'in', ['sale','cancel']),('delivery_status', '!=', False)]}"/> attrs="{'invisible': ['|','&amp;','|',('check_status', '!=', 'approved'),('state', 'in', ['draft','cancel']),'&amp;','&amp;',('check_status', '=', 'approved'),('state', 'in', ['sale','cancel']),('delivery_status', '!=', False),('state', 'in', ['cancel'])]}"/>
</xpath> </xpath>
<xpath expr="//form/header/button[@name='action_cancel']" position="attributes"> <xpath expr="//form/header/button[@name='action_cancel']" position="attributes">
<attribute name="attrs">{'invisible': ['|','&amp;',('check_status', '!=', 'approved'),('state', <attribute name="attrs">{'invisible': ['|','&amp;','|', ('check_status', '!=', 'approved'),('state',
'in', ['draft','cancel']),'&amp;','&amp;',('check_status', '=', 'approved'),('state', 'in', 'in', ['draft','cancel']),'&amp;','&amp;',('check_status', '=', 'approved'),('state', 'in',
['sale','cancel']),('delivery_status', '!=', False)]} ['sale','cancel']),('delivery_status', '!=', False), ('state', 'in', ['cancel'])]}
</attribute> </attribute>
</xpath> </xpath>
<xpath expr="//form/header/button[@name='action_draft']" position="attributes"> <xpath expr="//form/header/button[@name='action_draft']" position="attributes">

View File

@@ -94,47 +94,47 @@ class MachineTableToolChangingApply(models.Model):
if len(records) > 1: if len(records) > 1:
raise ValidationError('该刀位号已存在,请重新选择!!!') raise ValidationError('该刀位号已存在,请重新选择!!!')
@api.constrains('functional_tool_status') # @api.constrains('functional_tool_status')
def automation_apply_for_tool_change(self): # def automation_apply_for_tool_change(self):
""" # """
自动申请换刀 # 自动申请换刀
:return: # :return:
""" # """
# 更新数据到机台换刀申请界面 # # 更新数据到机台换刀申请界面
if self.functional_tool_status == '报警' and not self.sf_functional_tool_assembly_id: # if self.functional_tool_status == '报警' and not self.sf_functional_tool_assembly_id:
machine_table_tool_changing_apply = self.env['sf.machine.table.tool.changing.apply'].search( # machine_table_tool_changing_apply = self.env['sf.machine.table.tool.changing.apply'].search(
[('maintenance_equipment_id', '=', self.maintenance_equipment_id.id), # [('maintenance_equipment_id', '=', self.maintenance_equipment_id.id),
('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id) # ('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id)
]) # ])
#
# 创建功能刀具预警记录 # # 创建功能刀具预警记录
self.env['sf.functional.tool.warning'].create_tool_warning_record({'tool_changing_apply_id': self}) # self.env['sf.functional.tool.warning'].create_tool_warning_record({'tool_changing_apply_id': self})
#
# 新建组装任务 # # 新建组装任务
sf_functional_tool_assembly = self.env['sf.functional.tool.assembly'].create({ # sf_functional_tool_assembly = self.env['sf.functional.tool.assembly'].create({
'functional_tool_name': self.functional_tool_name, # 'functional_tool_name': self.functional_tool_name,
'functional_tool_type_id': self.functional_tool_type_id.id, # 'functional_tool_type_id': self.functional_tool_type_id.id,
'functional_tool_diameter': self.diameter, # 'functional_tool_diameter': self.diameter,
'knife_tip_r_angle': self.knife_tip_r_angle, # 'knife_tip_r_angle': self.knife_tip_r_angle,
'coarse_middle_thin': '3', # 'coarse_middle_thin': '3',
'new_former': '0', # 'new_former': '0',
'functional_tool_length': self.extension_length, # 'functional_tool_length': self.extension_length,
'effective_length': self.effective_length, # 'effective_length': self.effective_length,
'loading_task_source': '1', # 'loading_task_source': '1',
'use_tool_time': fields.Datetime.now() + timedelta(hours=4), # 'use_tool_time': fields.Datetime.now() + timedelta(hours=4),
'production_line_name_id': self.production_line_id.id, # 'production_line_name_id': self.production_line_id.id,
'machine_tool_name_id': self.maintenance_equipment_id.id, # 'machine_tool_name_id': self.maintenance_equipment_id.id,
'applicant': '系统自动', # 'applicant': '系统自动',
'apply_time': fields.Datetime.now(), # 'apply_time': fields.Datetime.now(),
'cutter_spacing_code_id': self.cutter_spacing_code_id.id, # 'cutter_spacing_code_id': self.cutter_spacing_code_id.id,
'whether_standard_knife': self.whether_standard_knife, # 'whether_standard_knife': self.whether_standard_knife,
'reason_for_applying': '机台报警自动换刀', # 'reason_for_applying': '机台报警自动换刀',
'sf_machine_table_tool_changing_apply_id': self.id # 'sf_machine_table_tool_changing_apply_id': self.id
}) # })
#
machine_table_tool_changing_apply.write( # machine_table_tool_changing_apply.write(
{'status': '1', # {'status': '1',
'sf_functional_tool_assembly_id': sf_functional_tool_assembly.id}) # 'sf_functional_tool_assembly_id': sf_functional_tool_assembly.id})
def revocation_1(self): def revocation_1(self):
""" """
@@ -760,6 +760,15 @@ class FunctionalToolDismantle(models.Model):
functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True, tracking=True, functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True, tracking=True,
domain=[('functional_tool_status', '!=', '已拆除'), domain=[('functional_tool_status', '!=', '已拆除'),
('current_location', '=', '刀具房')]) ('current_location', '=', '刀具房')])
@api.onchange('functional_tool_id')
def _onchange_functional_tool_id(self):
for item in self:
if item:
dismantle_id = self.search([('functional_tool_id', '=', item.functional_tool_id.id)])
if dismantle_id:
raise ValidationError(f'Rfid为【{item.rfid}】的功能刀具已经存在拆解单,单号是【{dismantle_id[0].code}')
tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True, tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
compute='_compute_functional_tool_num') compute='_compute_functional_tool_num')
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_functional_tool_num', store=True) tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_functional_tool_num', store=True)
@@ -938,15 +947,23 @@ class FunctionalToolDismantle(models.Model):
if self.chuck_freight_id == self.pad_freight_id: if self.chuck_freight_id == self.pad_freight_id:
raise ValidationError('【夹头】和【刀盘】的目标货位重复,请重新选择!') raise ValidationError('【夹头】和【刀盘】的目标货位重复,请重新选择!')
def tool_scrap(self):
self.scrap_boolean = True
def tool_no_scrap(self):
self.scrap_boolean = False
def confirmation_disassembly(self): def confirmation_disassembly(self):
logging.info('%s刀具确认开始拆解' % self.dismantle_cause) logging.info('%s刀具确认开始拆解' % self.dismantle_cause)
code = self.code code = self.code
if self.functional_tool_id.functional_tool_status == '已拆除': if self.functional_tool_id.functional_tool_status == '已拆除':
raise ValidationError('Rfid为【%s】的功能刀具已经拆解,请勿重复操作!' % self.functional_tool_id.rfid_dismantle) raise ValidationError('Rfid为【%s名称为【%s的功能刀具已经拆解,请勿重复操作!' % (
self.functional_tool_id.rfid_dismantle, self.name))
# 对拆解的功能刀具进行校验,只有在刀具房的功能刀具才能拆解 # 对拆解的功能刀具进行校验,只有在刀具房的功能刀具才能拆解
if self.functional_tool_id.tool_room_num == 0: elif self.functional_tool_id.functional_tool_status != '报警':
raise ValidationError('Rfid为【%s】的功能刀具当前位置为【%s】,不能进行拆解!' % ( if self.functional_tool_id.tool_room_num == 0:
self.rfid, self.functional_tool_id.current_location)) raise ValidationError('Rfid为【%s】的功能刀具当前位置为【%s】,不能进行拆解!' % (
self.rfid, self.functional_tool_id.current_location))
# 目标重复校验 # 目标重复校验
self.location_duplicate_check() self.location_duplicate_check()
datas = {'scrap': [], 'picking': []} datas = {'scrap': [], 'picking': []}
@@ -1005,6 +1022,14 @@ class FunctionalToolDismantle(models.Model):
'rfid': '%s(已拆解)' % self.rfid, 'rfid': '%s(已拆解)' % self.rfid,
'state': '已拆解' 'state': '已拆解'
}) })
# ==================修改刀具预警信息的值============
warning_id = self.env['sf.functional.tool.warning'].sudo().search(
[('functional_tool_id', '=', self.functional_tool_id.id)])
if warning_id:
warning_id.sudo().write({
'dispose_user': self.env.user.name,
'dispose_time': fields.Datetime.now()
})
logging.info('%s】刀具拆解成功!' % self.name) logging.info('%s】刀具拆解成功!' % self.name)
def create_tool_picking_scrap(self, datas): def create_tool_picking_scrap(self, datas):

View File

@@ -11,6 +11,7 @@ from odoo.exceptions import ValidationError
class FunctionalCuttingToolEntity(models.Model): class FunctionalCuttingToolEntity(models.Model):
_name = 'sf.functional.cutting.tool.entity' _name = 'sf.functional.cutting.tool.entity'
_description = '功能刀具列表' _description = '功能刀具列表'
_order = 'functional_tool_status'
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具组装单', readonly=True) functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具组装单', readonly=True)
@@ -53,6 +54,22 @@ class FunctionalCuttingToolEntity(models.Model):
safe_inventory_id = fields.Many2one('sf.real.time.distribution.of.functional.tools', safe_inventory_id = fields.Many2one('sf.real.time.distribution.of.functional.tools',
string='功能刀具安全库存', readonly=True) string='功能刀具安全库存', readonly=True)
@api.onchange('functional_tool_status')
def _onchange_functional_tool_status(self):
for item in self:
if item:
if item.functional_tool_status == '报警':
# 创建报警刀具拆解单
self.env['sf.functional.tool.dismantle'].sudo().create({
'functional_tool_id': item.ids[0],
'dismantle_cause': '寿命到期报废'
})
# 创建刀具报警记录
self.env['sf.functional.tool.warning'].sudo().create({
'rfid': item.rfid,
'functional_tool_id': item.ids[0]
})
@api.depends('barcode_id.quant_ids', 'barcode_id.quant_ids.location_id', 'functional_tool_status', @api.depends('barcode_id.quant_ids', 'barcode_id.quant_ids.location_id', 'functional_tool_status',
'current_shelf_location_id') 'current_shelf_location_id')
def _compute_current_location_id(self): def _compute_current_location_id(self):
@@ -101,27 +118,28 @@ class FunctionalCuttingToolEntity(models.Model):
def tool_in_out_stock_location(self, location_id): def tool_in_out_stock_location(self, location_id):
tool_room_id = self.env['stock.location'].search([('name', '=', '刀具房')]) tool_room_id = self.env['stock.location'].search([('name', '=', '刀具房')])
pre_manufacturing_id = self.env['stock.location'].search([('name', '=', '制造前')]) pre_manufacturing_id = self.env['stock.location'].search([('name', '=', '制造前')])
for item in self: if self:
# 中控反馈该位置有刀 for item in self:
if item: # 中控反馈该位置有刀
# 系统该位置有刀 if item:
if location_id.product_sn_id: # 系统该位置有刀
# 中控反馈和系统中,该位置是同一把刀 if location_id.product_sn_id:
if item.barcode_id == location_id.product_sn_id: # 中控反馈和系统中,该位置是同一把刀
return True if item.barcode_id == location_id.product_sn_id:
# 中控反馈和系统中,该位置不是同一把刀 return True
else: # 中控反馈和系统中,该位置不是同一把刀
# 原刀从线边出库 else:
item.tool_in_out_stock_location_1(location_id, tool_room_id) # 原刀从线边出库
# 新刀入库到线边 item.tool_in_out_stock_location_1(location_id, tool_room_id)
item.create_stock_move(pre_manufacturing_id, location_id) # 新刀入库到线边
item.current_shelf_location_id = location_id.id item.create_stock_move(pre_manufacturing_id, location_id)
item.current_shelf_location_id = location_id.id
# 中控反馈该位置没有刀 # 中控反馈该位置没有刀
else: else:
# 系统该位置有刀 # 系统该位置有刀
if location_id.product_sn_id: if location_id.product_sn_id:
item.tool_in_out_stock_location_1(location_id, tool_room_id) self.tool_in_out_stock_location_1(location_id, tool_room_id)
def tool_in_out_stock_location_1(self, location_id, tool_room_id): def tool_in_out_stock_location_1(self, location_id, tool_room_id):
tool = self.env['sf.functional.cutting.tool.entity'].search( tool = self.env['sf.functional.cutting.tool.entity'].search(
@@ -238,10 +256,39 @@ class FunctionalCuttingToolEntity(models.Model):
functional_tool_model_ids.append(functional_tool_model.id) functional_tool_model_ids.append(functional_tool_model.id)
return [(6, 0, functional_tool_model_ids)] return [(6, 0, functional_tool_model_ids)]
dismantle_num = fields.Integer('拆解单数量', compute='_compute_dismantle_num', store=True)
dismantle_ids = fields.One2many('sf.functional.tool.dismantle', 'functional_tool_id', '拆解单')
@api.depends('dismantle_ids')
def _compute_dismantle_num(self):
for item in self:
if item:
item.dismantle_num = len(item.dismantle_ids)
def open_functional_tool_dismantle_form(self):
self.ensure_one()
dismantle_ids = self.env['sf.functional.tool.dismantle'].sudo().search([('functional_tool_id', '=', self.id)])
action = {
'res_model': 'sf.functional.tool.dismantle',
'type': 'ir.actions.act_window',
'name': '拆解单',
}
if len(dismantle_ids) == 1:
action.update({
'view_mode': 'form',
'res_id': dismantle_ids[0].id,
})
else:
action.update({
'domain': [('id', 'in', dismantle_ids.ids)],
'view_mode': 'tree,form',
})
return action
def open_functional_tool_warning(self): def open_functional_tool_warning(self):
action = self.env.ref('sf_tool_management.action_sf_functional_tool_warning') action = self.env.ref('sf_tool_management.action_sf_functional_tool_warning')
result = action.read()[0] result = action.read()[0]
result['domain'] = [('functional_tool_name_id', '=', self.functional_tool_name_id.id)] result['domain'] = [('functional_tool_id', '=', self.id)]
return result return result
def open_stock_move_line(self): def open_stock_move_line(self):
@@ -323,10 +370,10 @@ class FunctionalToolWarning(models.Model):
_name = 'sf.functional.tool.warning' _name = 'sf.functional.tool.warning'
_description = '功能刀具预警' _description = '功能刀具预警'
code = fields.Char('编码', related='functional_tool_name_id.code') code = fields.Char('编码', related='functional_tool_id.code')
rfid = fields.Char('Rfid', related='functional_tool_name_id.rfid') rfid = fields.Char('Rfid', readonly=True)
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id') tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_id.tool_groups_id')
name = fields.Char('名称', invisible=True, readonly=True, related='functional_tool_name_id.name') name = fields.Char('名称', invisible=True, readonly=True, related='functional_tool_id.name')
# 机床信息 # 机床信息
production_line_id = fields.Many2one('sf.production.line', string='生产线', production_line_id = fields.Many2one('sf.production.line', string='生产线',
group_expand='_read_group_machine_table_name_ids') group_expand='_read_group_machine_table_name_ids')
@@ -337,52 +384,77 @@ class FunctionalToolWarning(models.Model):
cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号',
domain="[('equipment_id', '=', maintenance_equipment_id)]") domain="[('equipment_id', '=', maintenance_equipment_id)]")
# 功能刀具信息 # 功能刀具信息
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称') functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', string='功能刀具', readonly=True)
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', related='functional_tool_name_id.barcode_id') barcode_id = fields.Many2one('stock.lot', string='序列号', related='functional_tool_id.barcode_id')
mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型') mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
diameter = fields.Float(string='刀具直径(mm)') related='functional_tool_id.sf_cutting_tool_type_id')
knife_tip_r_angle = fields.Float(string='尖R角(mm)') diameter = fields.Float(string='具直径(mm)', related='functional_tool_id.functional_tool_diameter')
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', related='functional_tool_id.knife_tip_r_angle')
# 其他信息 # 其他信息
install_tool_time = fields.Datetime("刀具组装时间", related='functional_tool_name_id.tool_loading_time') install_tool_time = fields.Datetime("刀具组装时间", related='functional_tool_name_id.tool_loading_time')
on_board_time = fields.Datetime('上机装刀时间') on_board_time = fields.Datetime('上机装刀时间')
max_lifetime_value = fields.Integer(string='最大寿命值(min)') max_lifetime_value = fields.Integer(string='最大寿命值(min)', related='functional_tool_id.max_lifetime_value')
alarm_value = fields.Integer(string='报警值(min)') alarm_value = fields.Integer(string='报警值(min)', related='functional_tool_id.alarm_value')
used_value = fields.Integer(string='已使用值(min)') used_value = fields.Integer(string='已使用值(min)', related='functional_tool_id.used_value')
functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')], string='状态') functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')], string='状态')
alarm_time = fields.Datetime('报警时间') alarm_time = fields.Datetime('报警时间', default=lambda self: fields.Datetime.now(), readonly=True)
dispose_user = fields.Char('处理人') dispose_user = fields.Char('处理人', readonly=True)
dispose_time = fields.Char('处理时间') dispose_time = fields.Char('处理时间', readonly=True)
dispose_func = fields.Char('处理方法/措施', readonly=False) dispose_func = fields.Char('处理方法/措施', readonly=True)
active = fields.Boolean(string='已归档', default=True) active = fields.Boolean(string='已归档', default=True)
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称')
@api.model @api.model
def _read_group_machine_table_name_ids(self, categories, domain, order): def _read_group_machine_table_name_ids(self, categories, domain, order):
machine_table_name_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID) machine_table_name_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
return categories.browse(machine_table_name_ids) return categories.browse(machine_table_name_ids)
def create_tool_warning_record(self, obj): def action_open_dismantle(self):
""" self.ensure_one()
机台换刀申请报警状态时,创建功能刀具预警记录 dismantle_ids = self.env['sf.functional.tool.dismantle'].sudo().search(
""" [('functional_tool_id', '=', self.functional_tool_id.id)])
if obj: action = {
for tool in obj.get('tool_changing_apply_id'): 'res_model': 'sf.functional.tool.dismantle',
self.env['sf.functional.tool.warning'].create({ 'type': 'ir.actions.act_window',
'production_line_id': tool.production_line_id.id, 'name': '拆解单'
'maintenance_equipment_id': tool.maintenance_equipment_id.id, }
'machine_tool_code': tool.machine_tool_code, if len(dismantle_ids) == 1:
'machine_table_type_id': tool.machine_table_type_id.id, action.update({
'cutter_spacing_code_id': tool.cutter_spacing_code_id.id, 'view_mode': 'form',
'functional_tool_name_id': tool.functional_tool_name_id.id, 'res_id': dismantle_ids.ids[0]
'barcode_id': tool.barcode_id.id, })
'diameter': tool.diameter, elif dismantle_ids:
'knife_tip_r_angle': tool.knife_tip_r_angle, action.update({
'max_lifetime_value': tool.max_lifetime_value, 'view_mode': 'tree,form',
'alarm_value': tool.alarm_value, 'domain': [('id', 'in', dismantle_ids.ids)],
'used_value': tool.used_value, })
'functional_tool_status': tool.functional_tool_status, else:
'alarm_time': fields.Datetime.now(), return False
}) return action
# 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): class StockMoveLine(models.Model):

View File

@@ -53,7 +53,7 @@ class SfMaintenanceEquipment(models.Model):
params = {"DeviceId": self.name} params = {"DeviceId": self.name}
r = requests.get(crea_url, params=params, headers=headers) r = requests.get(crea_url, params=params, headers=headers)
ret = r.json() ret = r.json()
logging.info('register_equipment_tool:%s' % ret) logging.info('机床刀库register_equipment_tool():%s' % ret)
datas = ret['Datas'] datas = ret['Datas']
self.write_maintenance_equipment_tool(datas) self.write_maintenance_equipment_tool(datas)
if ret['Succeed']: if ret['Succeed']:

View File

@@ -25,7 +25,10 @@
<field name="max_lifetime_value"/> <field name="max_lifetime_value"/>
<field name="alarm_value"/> <field name="alarm_value"/>
<field name="used_value"/> <field name="used_value"/>
<field name="functional_tool_status"/> <field name="functional_tool_status" widget='badge'
decoration-success="functional_tool_status == '正常'"
decoration-muted="functional_tool_status == '已拆除'"
decoration-danger="functional_tool_status == '报警'"/>
<field name="current_location" string="当前位置"/> <field name="current_location" string="当前位置"/>
<field name="current_location_id" invisible="1"/> <field name="current_location_id" invisible="1"/>
@@ -48,6 +51,18 @@
<div class="oe_button_box" name="button_box"> <div class="oe_button_box" name="button_box">
<!-- <button name="button_safe_inventory_id" string="更新功能刀具关联的安全库存记录"--> <!-- <button name="button_safe_inventory_id" string="更新功能刀具关联的安全库存记录"-->
<!-- type="object" class="btn-primary"/>--> <!-- type="object" class="btn-primary"/>-->
<button class="oe_stat_button" groups="sf_base.group_sf_mrp_user"
name="open_functional_tool_dismantle_form"
icon="fa-credit-card"
type="object"
attrs="{'invisible': [('dismantle_num', '=', 0)]}">
<div name="dismantle_num" class="o_field_widget o_readonly_modifier o_field_statinfo">
<span class="o_stat_info o_stat_value">
<field name="dismantle_num"/>
</span>
<span class="o_stat_text">拆解单</span>
</div>
</button>
<button class="oe_stat_button" groups="sf_base.group_sf_mrp_user" <button class="oe_stat_button" groups="sf_base.group_sf_mrp_user"
name="open_functional_tool_warning" name="open_functional_tool_warning"
icon="fa-list-ul" icon="fa-list-ul"
@@ -235,26 +250,29 @@
<field name="name">sf.functional.tool.warning.tree</field> <field name="name">sf.functional.tool.warning.tree</field>
<field name="model">sf.functional.tool.warning</field> <field name="model">sf.functional.tool.warning</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="功能刀具预警" create="0" edit="0" delete="0" editable="bottom"> <tree string="功能刀具预警" create="0" edit="0" delete="0" editable="bottom" default_order="id desc"
<field name="production_line_id" optional="hide"/> action="action_open_dismantle" type="object">
<field name="maintenance_equipment_id" optional="hide"/> <field name="production_line_id" invisible="1"/>
<field name="machine_tool_code"/> <field name="maintenance_equipment_id" invisible="1"/>
<field name="cutter_spacing_code_id"/> <field name="machine_tool_code" invisible="1"/>
<field name="barcode_id" invisible="1"/> <field name="cutter_spacing_code_id" invisible="1"/>
<field name="on_board_time" invisible="1"/>
<field name="functional_tool_status" invisible="1"/>
<field name="functional_tool_name_id" invisible="1"/>
<field name="rfid"/> <field name="rfid"/>
<field name="functional_tool_name_id"/> <field name="functional_tool_id"/>
<field name="diameter"/> <field name="barcode_id" optional="hide"/>
<field name="knife_tip_r_angle"/> <field name="diameter" optional="hide"/>
<field name="knife_tip_r_angle" optional="hide"/>
<field name="install_tool_time" optional="hide"/> <field name="install_tool_time" optional="hide"/>
<field name="on_board_time" optional="hide"/>
<field name="max_lifetime_value"/> <field name="max_lifetime_value"/>
<field name="alarm_value"/> <field name="alarm_value"/>
<field name="used_value"/> <field name="used_value"/>
<field name="functional_tool_status"/>
<field name="alarm_time"/> <field name="alarm_time"/>
<field name="dispose_user"/> <field name="dispose_user"/>
<field name="dispose_time"/> <field name="dispose_time"/>
<field name="dispose_func"/> <field name="dispose_func" optional="hide"/>
<!-- <button name="enroll_functional_tool_warning" string="刀具预警注册" type="object"--> <!-- <button name="enroll_functional_tool_warning" string="刀具预警注册" type="object"-->
<!-- class="btn-primary"/>--> <!-- class="btn-primary"/>-->
</tree> </tree>
@@ -266,31 +284,19 @@
<field name="model">sf.functional.tool.warning</field> <field name="model">sf.functional.tool.warning</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="功能刀具预警"> <search string="功能刀具预警">
<field name="machine_tool_code"/>
<field name="cutter_spacing_code_id"/>
<field name="barcode_id"/> <field name="barcode_id"/>
<field name="rfid"/> <field name="rfid"/>
<field name="functional_tool_name_id"/> <field name="functional_tool_name_id"/>
<field name="diameter"/>
<field name="knife_tip_r_angle"/>
<field name="install_tool_time" optional="hide"/>
<field name="on_board_time" optional="hide"/>
<field name="max_lifetime_value"/>
<field name="alarm_value"/>
<field name="used_value"/>
<field name="functional_tool_status"/>
<field name="alarm_time"/>
<field name="dispose_user"/>
<field name="dispose_time"/>
<field name="dispose_func"/>
<field name="production_line_id" invisible="True"/>
<filter string="已归档" name="inactive" domain="[('active', '=', False)]"/>
<searchpanel> <searchpanel>
<field name="production_line_id" icon="fa-building" enable_counters="1"/> <field name="production_line_id" icon="fa-building" enable_counters="1"/>
<field name="maintenance_equipment_id" icon="fa-building" enable_counters="1"/> <field name="maintenance_equipment_id" icon="fa-building" enable_counters="1"/>
<field name="cutter_spacing_code_id" icon="fa-building" enable_counters="1"/> <field name="cutter_spacing_code_id" icon="fa-building" enable_counters="1"/>
<field name="functional_tool_status" icon="fa-building" enable_counters="1"/> <field name="functional_tool_status" icon="fa-building" enable_counters="1"/>
</searchpanel> </searchpanel>
<group expand="0">
<filter string="报警时间" name="alarm_time" domain="[]"
context="{'group_by': 'alarm_time'}"/>
</group>
</search> </search>
</field> </field>
</record> </record>

View File

@@ -704,10 +704,10 @@
<field name="model">sf.functional.tool.assembly</field> <field name="model">sf.functional.tool.assembly</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search> <search>
<field name="functional_tool_name"/>
<field name="assembly_order_code"/> <field name="assembly_order_code"/>
<field name="code" string="功能刀具编码"/> <field name="code" string="功能刀具编码"/>
<field name="barcode_id"/> <field name="barcode_id"/>
<field name="functional_tool_name"/>
<field name="functional_tool_type_id"/> <field name="functional_tool_type_id"/>
<field name="tool_groups_id"/> <field name="tool_groups_id"/>
<field name="loading_task_source" string="任务来源"/> <field name="loading_task_source" string="任务来源"/>
@@ -800,10 +800,16 @@
</h1> </h1>
</div> </div>
<field name="_barcode_scanned" widget="barcode_handler"/> <field name="_barcode_scanned" widget="barcode_handler"/>
<script>
setTimeout(function(){
$('#functional_tool_id').blur()
}, 100)
</script>
<group> <group>
<group> <group>
<field name="functional_tool_id" placeholder="请选择将要拆解的功能刀具" <field name="functional_tool_id" placeholder="请选择将要拆解的功能刀具"
options="{'no_create': True}" attrs="{'readonly': [('state', '=', '已拆解')]}"/> options="{'no_create': True}"
attrs="{'readonly': ['|',('state', '=', '已拆解'),('id', '!=', False)]}"/>
<field name="rfid" attrs="{'invisible': [('rfid', '=', '')]}"/> <field name="rfid" attrs="{'invisible': [('rfid', '=', '')]}"/>
<field name="rfid_dismantle" attrs="{'invisible': [('rfid_dismantle', '=', False)]}"/> <field name="rfid_dismantle" attrs="{'invisible': [('rfid_dismantle', '=', False)]}"/>
<field name="tool_type_id"/> <field name="tool_type_id"/>
@@ -833,10 +839,26 @@
<notebook> <notebook>
<page string="物料组装信息"> <page string="物料组装信息">
<group> <group>
<group string="刀柄" attrs="{'invisible': [('handle_product_id', '=', False)]}"> <group string="刀柄" attrs="{'invisible': [('handle_product_id', '=', False)]}"
col="1">
<group attrs="{'invisible': [('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])]}">
<group col="3">
<group>
<field name="scrap_boolean" string="是否报废"/>
</group>
<group></group>
<group>
<button string="报废" name="tool_scrap" type="object"
class="btn-primary" confirm="是否确认报废刀柄"
attrs="{'invisible': [('scrap_boolean', '=', True)]}"/>
<button string="取消" name="tool_no_scrap" type="object"
class="btn-primary" confirm="是否取消报废刀柄"
attrs="{'invisible': [('scrap_boolean', '=', False)]}"/>
<group></group>
</group>
</group>
</group>
<group> <group>
<field name="scrap_boolean" string="是否报废"
attrs="{'invisible': [('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])], 'readonly': [('state', '=', '已拆解')]}"/>
<field name="handle_rfid" string="Rfid"/> <field name="handle_rfid" string="Rfid"/>
<field name="handle_lot_id" string="序列号"/> <field name="handle_lot_id" string="序列号"/>
<field name="handle_product_id" string="名称"/> <field name="handle_product_id" string="名称"/>
@@ -911,7 +933,7 @@
</group> </group>
</group> </group>
</page> </page>
<page string="报废" <page string="报废"
attrs="{'invisible':[('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])]}"> attrs="{'invisible':[('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])]}">
<field name="scrap_ids"> <field name="scrap_ids">
<tree> <tree>
@@ -952,8 +974,9 @@
<field name="model">sf.functional.tool.dismantle</field> <field name="model">sf.functional.tool.dismantle</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search> <search>
<field name="rfid"/>
<field name="functional_tool_id"/> <field name="functional_tool_id"/>
<field name="code" string="拆解单编码"/> <field name="code" string="拆解单"/>
<filter name="no_dismantle_state" string="未拆解" domain="[('state','!=','已拆解')]"/> <filter name="no_dismantle_state" string="未拆解" domain="[('state','!=','已拆解')]"/>
<filter name="dismantle_state" string="已拆解" domain="[('state','=','已拆解')]"/> <filter name="dismantle_state" string="已拆解" domain="[('state','=','已拆解')]"/>
<separator/> <separator/>

View File

@@ -842,6 +842,8 @@ class StockPicking(models.Model):
stock_move_id = self.env['stock.move'] stock_move_id = self.env['stock.move']
datas = {'data': [], 'picking_id': picking_id} datas = {'data': [], 'picking_id': picking_id}
if obj.handle_code_id: if obj.handle_code_id:
# 修改刀柄序列号状态为【在用】
obj.handle_code_id.sudo().write({'tool_material_status': '在用'})
datas['data'].append( datas['data'].append(
{'current_location_id': self.env['sf.shelf.location'], 'lot_id': obj.handle_code_id}) {'current_location_id': self.env['sf.shelf.location'], 'lot_id': obj.handle_code_id})
if obj.integral_product_id: if obj.integral_product_id:

View File

@@ -201,6 +201,11 @@
</group> </group>
</group> </group>
</group> </group>
<script>
setTimeout(function(){
$('#handle_code_id').blur()
}, 100)
</script>
<group string="组装物料信息" col="1"> <group string="组装物料信息" col="1">
<field name="_barcode_scanned" widget="barcode_handler"/> <field name="_barcode_scanned" widget="barcode_handler"/>
<group col="1"> <group col="1">
@@ -368,7 +373,7 @@
<group> <group>
<field name="obtain_measurement_status" invisible="1"/> <field name="obtain_measurement_status" invisible="1"/>
<button name="get_tool_preset_parameter" string="获取测量值" type="object" <button name="get_tool_preset_parameter" string="获取测量值" type="object"
attrs="{'invisible': [('enable_tool_presetter', '=', False)]}" attrs="{'invisible': [('enable_tool_presetter', '=', False)]}"
class="btn-primary"/> class="btn-primary"/>
</group> </group>
</group> </group>

View File

@@ -507,13 +507,13 @@ class ShelfLocation(models.Model):
print('eeeeeee空闲', e) print('eeeeeee空闲', e)
# 调取获取货位信息接口 # 调取获取货位信息接口
def get_sf_shelf_location_info(self): def get_sf_shelf_location_info(self, device_id='Cabinet-AL'):
config = self.env['res.config.settings'].get_values() config = self.env['res.config.settings'].get_values()
headers = {'Authorization': config['center_control_Authorization']} headers = {'Authorization': config['center_control_Authorization']}
crea_url = config['center_control_url'] + "/AutoDeviceApi/GetLocationInfos" crea_url = config['center_control_url'] + "/AutoDeviceApi/GetLocationInfos"
params = {'DeviceId': 'Cabinet-AL'} params = {'DeviceId': device_id}
r = requests.get(crea_url, params=params, headers=headers) r = requests.get(crea_url, params=params, headers=headers)
ret = r.json() ret = r.json()

View File

@@ -13,88 +13,92 @@ class MrsShelfLocationDataSync(models.Model):
_name = 'sf.shelf.location.datasync' _name = 'sf.shelf.location.datasync'
_description = '同步库存信息' _description = '同步库存信息'
def get_total_data(self):
# 建立对应关系的函数
def align_data(my_data, their_data):
paired_data = list(zip(my_data, their_data))
return paired_data
logging.info('============================get_total_data()======================')
shelf_1_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边刀架')], limit=1)
tool_location_objs_1 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_1_obj.id)], order='id')
location_codes_1 = [location.barcode for location in tool_location_objs_1]
print(location_codes_1)
# 对方的数据列表
their_data_1 = [f"ToolCab1-{i:02}" for i in range(1, 73)]
# 执行对齐
aligned_data_1 = align_data(location_codes_1, their_data_1)
# 2
shelf_2_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边刀架')], limit=1)
tool_location_objs_2 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_2_obj.id)], order='id')
location_codes_2 = [location.barcode for location in tool_location_objs_2]
print(location_codes_2)
# 对方的数据列表
their_data_2 = [f"ToolCab2-{i:02}" for i in range(1, 73)]
# 执行对齐
aligned_data_2 = align_data(location_codes_2, their_data_2)
# 4
shelf_4_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边料架')], limit=1)
tool_location_objs_4 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_4_obj.id)], order='id')
location_codes_4 = [location.barcode for location in tool_location_objs_4]
print(location_codes_4)
# 对方的数据列表
their_data_4 = [f"PartCab4-{i:02}" for i in range(1, 17)]
# 执行对齐
aligned_data_4 = align_data(location_codes_4, their_data_4)
# 3
shelf_3_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边料架')], limit=1)
tool_location_objs_3 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_3_obj.id)], order='id')
location_codes_3 = [location.barcode for location in tool_location_objs_3]
print(location_codes_3)
# 对方的数据列表
their_data_3 = [f"PartCab3-{i:02}" for i in range(1, 13)]
# 执行对齐
aligned_data_3 = align_data(location_codes_3, their_data_3)
# 5
shelf_5_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-三号线边料架')], limit=1)
tool_location_objs_5 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_5_obj.id)], order='id')
location_codes_5 = [location.barcode for location in tool_location_objs_5]
print(location_codes_5)
# 对方的数据列表
their_data_5 = [f"PartCab5-{i:02}" for i in range(1, 13)]
# 执行对齐
aligned_data_5 = align_data(location_codes_5, their_data_5)
total_data = aligned_data_1 + aligned_data_2 + aligned_data_3 + aligned_data_4 + aligned_data_5
print(total_data)
logging.info(f"total_data: {total_data}")
return total_data
def find_our_code(self, total_data, their_code):
for code_pair in total_data:
if code_pair[1] == their_code:
return code_pair[0]
return None # 如果没有找到对应的值返回None或适当的默认值
def _cron_shelf_location_datasync(self): def _cron_shelf_location_datasync(self):
try: try:
# 建立对应关系的函数
def align_data(my_data, their_data):
paired_data = list(zip(my_data, their_data))
return paired_data
shelf_1_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边刀架')], limit=1)
tool_location_objs_1 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_1_obj.id)], order='id')
location_codes_1 = [location.barcode for location in tool_location_objs_1]
print(location_codes_1)
# 对方的数据列表
their_data_1 = [f"ToolCab1-{i:02}" for i in range(1, 73)]
# 执行对齐
aligned_data_1 = align_data(location_codes_1, their_data_1)
# 2
shelf_2_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边刀架')], limit=1)
tool_location_objs_2 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_2_obj.id)], order='id')
location_codes_2 = [location.barcode for location in tool_location_objs_2]
print(location_codes_2)
# 对方的数据列表
their_data_2 = [f"ToolCab2-{i:02}" for i in range(1, 73)]
# 执行对齐
aligned_data_2 = align_data(location_codes_2, their_data_2)
# 4
shelf_4_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边料架')], limit=1)
tool_location_objs_4 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_4_obj.id)], order='id')
location_codes_4 = [location.barcode for location in tool_location_objs_4]
print(location_codes_4)
# 对方的数据列表
their_data_4 = [f"PartCab4-{i:02}" for i in range(1, 17)]
# 执行对齐
aligned_data_4 = align_data(location_codes_4, their_data_4)
# 3
shelf_3_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边料架')], limit=1)
tool_location_objs_3 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_3_obj.id)], order='id')
location_codes_3 = [location.barcode for location in tool_location_objs_3]
print(location_codes_3)
# 对方的数据列表
their_data_3 = [f"PartCab3-{i:02}" for i in range(1, 13)]
# 执行对齐
aligned_data_3 = align_data(location_codes_3, their_data_3)
# 5
shelf_5_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-三号线边料架')], limit=1)
tool_location_objs_5 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_5_obj.id)], order='id')
location_codes_5 = [location.barcode for location in tool_location_objs_5]
print(location_codes_5)
# 对方的数据列表
their_data_5 = [f"PartCab5-{i:02}" for i in range(1, 13)]
# 执行对齐
aligned_data_5 = align_data(location_codes_5, their_data_5)
total_data = aligned_data_1 + aligned_data_2 + aligned_data_3 + aligned_data_4 + aligned_data_5
print(total_data)
logging.info(f"total_data: {total_data}")
def find_their_code(my_code, aligned_data): def find_their_code(my_code, aligned_data):
for code_pair in aligned_data: for code_pair in aligned_data:
if code_pair[0] == my_code: if code_pair[0] == my_code:
return code_pair[1] return code_pair[1]
return None # 如果没有找到对应的值返回None或适当的默认值 return None # 如果没有找到对应的值返回None或适当的默认值
def find_our_code(their_code, aligned_data):
for code_pair in aligned_data:
if code_pair[1] == their_code:
return code_pair[0]
return None # 如果没有找到对应的值返回None或适当的默认值
# 定时更新所有设备机床刀库信息 # 定时更新所有设备机床刀库信息
equipment_ids = self.env['maintenance.equipment'].search( equipment_ids = self.env['maintenance.equipment'].search(
[('equipment_type', '=', '机床'), ('function_type', '!=', False)]) [('equipment_type', '=', '机床'), ('function_type', '!=', False)])
@@ -103,9 +107,10 @@ class MrsShelfLocationDataSync(models.Model):
equipment_id.register_equipment_tool() equipment_id.register_equipment_tool()
shelfinfo = self.env['sf.shelf.location'].get_sf_shelf_location_info() shelfinfo = self.env['sf.shelf.location'].get_sf_shelf_location_info()
total_data = self.get_total_data()
print('shelfinfo:', shelfinfo) print('shelfinfo:', shelfinfo)
for item in shelfinfo: for item in shelfinfo:
shelf_barcode = find_our_code(item['Postion'], total_data) shelf_barcode = self.find_our_code(total_data, item['Postion'])
location_id = self.env['sf.shelf.location'].search([('barcode', '=', shelf_barcode)], limit=1) location_id = self.env['sf.shelf.location'].search([('barcode', '=', shelf_barcode)], limit=1)
if location_id: if location_id:
# 如果是线边刀库信息,则对功能刀具移动生成记录 # 如果是线边刀库信息,则对功能刀具移动生成记录
@@ -115,6 +120,13 @@ class MrsShelfLocationDataSync(models.Model):
tool.tool_in_out_stock_location(location_id) tool.tool_in_out_stock_location(location_id)
if tool: if tool:
location_id.product_sn_id = tool.barcode_id.id location_id.product_sn_id = tool.barcode_id.id
# 修改功能刀具状态
tool_state = {'Nomal': '正常', 'Warning': '报警'}
if tool_state.get(item.get('State')):
if tool_state.get(item.get('State')) != tool.functional_tool_status:
tool.write({
'functional_tool_status': tool_state.get(item['State'])
})
else: else:
location_id.product_sn_id = False location_id.product_sn_id = False
else: else: