Compare commits

..

1 Commits

Author SHA1 Message Date
mgw
38e99a0f26 去掉货架货位打印不必要的逻辑 2024-06-13 15:29:15 +08:00
32 changed files with 689 additions and 1170 deletions

View File

@@ -32,11 +32,9 @@
options="{'no_create': True}"
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"
placeholder="请选择"/>
<field name="brand_id" options="{'no_create': True}" placeholder="请选择"
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_model_id" placeholder="请选择" class="custom_required"
options="{'no_create': True}"
domain="[('cutting_tool_material_id','=',cutting_tool_material_id),('brand_id', '=', brand_id)]"
domain="[('cutting_tool_material_id','=',cutting_tool_material_id)]"
context="{'default_cutting_tool_material_id': cutting_tool_material_id}"
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}">
</field>
@@ -50,10 +48,10 @@
<field name="fixture_material_id"
attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}"
placeholder="请选择" options="{'no_create': True}"/>
<field name="fixture_model_id" string="型号名称" placeholder="请选择" options="{'no_create': True}"
<field name="fixture_model_id" string="型号" placeholder="请选择" options="{'no_create': True}"
attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}"
domain="[('fixture_material_id','=',fixture_material_id)]"/>
<field name="specification_fixture_id" string="物料号" placeholder="请选择"
<field name="specification_fixture_id" string="规格" placeholder="请选择"
options="{'no_create': True}"
attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}"
domain="[('fixture_model_id','=',fixture_model_id)]"/>
@@ -98,16 +96,6 @@
</group>
</page>
</xpath>
<xpath expr="//field[@name='name']" position="attributes">
<attribute name="attrs">{'readonly': ['|',('id','!=',False),('categ_type', '=',
'刀具')], 'required': True}
</attribute>
</xpath>
<!-- <xpath expr="//field[@name='default_code']" position="attributes">-->
<!-- <attribute name="attrs">{'readonly': [('categ_type', '=', '刀具')], 'invisible':-->
<!-- [('product_variant_count', '>' , 1)]}-->
<!-- </attribute>-->
<!-- </xpath>-->
</field>
</record>
@@ -305,7 +293,7 @@
<field name="cutting_tool_blade_type"
attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_coarse_medium_fine" string="粗/中/精" placeholder="请选择"
attrs="{'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))],'readonly': [('id', '!=', False)]}"/>
attrs="{'required': [('cutting_tool_type','=','整体式刀具')],'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))],'readonly': [('id', '!=', False)]}"/>
<!--整体式刀具-->
<field name="cutting_tool_shank_diameter" string="柄部直径(mm)" class="diameter"
attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/>
@@ -468,8 +456,7 @@
<tree editable="bottom">
<!-- <field name="cutting_speed"-->
<!-- attrs="{'readonly': [('materials_type_id','!=',False)]}"/>-->
<field name="materials_type_id" options="{'no_create': True}"
placeholder="请选择"/>
<field name="materials_type_id" options="{'no_create': True}" placeholder="请选择"/>
<field name="blade_diameter"/>
<field name="feed_per_tooth"/>
</tree>

View File

@@ -8,7 +8,7 @@ from odoo.http import request
class Manufacturing_Connect(http.Controller):
@http.route('/AutoDeviceApi/GetWoInfo', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
@http.route('/AutoDeviceApi/GetWoInfo', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*")
def get_Work_Info(self, **kw):
"""
@@ -215,9 +215,7 @@ class Manufacturing_Connect(http.Controller):
if workorder.state != 'progress':
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '该工单未开始'}
return json.JSONEncoder().encode(res)
# workorder.write({'date_finished': datetime.now()})
if ret['IsComplete'] is True:
workorder.button_finish()
workorder.write({'date_finished': datetime.now()})
# workorder.process_state = '待解除装夹'
# workorder.sudo().production_id.process_state = '待解除装夹'

View File

@@ -178,7 +178,7 @@ class MrpProduction(models.Model):
raise UserError("更新程单失败,请联系管理员")
# cnc程序获取
def fetchCNC(self, production_names):
def fetchCNC(self, production_names, scrap_production):
cnc = self.env['mrp.production'].search([('id', '=', self.id)])
quick_order = self.env['quick.easy.order'].search(
[('name', '=', cnc.product_id.default_code.rsplit('-', 1)[0])])
@@ -194,7 +194,8 @@ class MrpProduction(models.Model):
'production_no': production_names,
'machine_tool_code': '',
'product_name': cnc.product_id.name,
'remanufacture_type': '',
'remanufacture_type': '' if not scrap_production else scrap_production.workorder_ids.filtered(
lambda b: b.routing_type == "CNC加工").test_results,
'model_code': cnc.product_id.model_code,
'material_code': self.env['sf.production.materials'].search(
[('id', '=', cnc.product_id.materials_id.id)]).materials_no,
@@ -292,7 +293,7 @@ class MrpProduction(models.Model):
# 则根据设备找到工作中心;否则采用前面描述的工作中心分配机制;
# 其他规则限制: 默认只分配给工作中心状态为非故障的工作中心;
def _create_workorder3(self):
def _create_workorder3(self, is_fetchcnc=False, scrap_production=False):
# 根据product_id对self进行分组
grouped_product_ids = {k: list(g) for k, g in groupby(self, key=lambda x: x.product_id.id)}
# 初始化一个字典来存储每个product_id对应的生产订单名称列表
@@ -335,8 +336,12 @@ class MrpProduction(models.Model):
production_programming = self.search(
[('product_id.id', '=', production.product_id.id), ('origin', '=', production.origin)],
limit=1, order='id asc')
if not production_programming.programming_no:
production.fetchCNC(', '.join(product_id_to_production_names[production.product_id.id]))
if not production_programming.programming_no or (is_fetchcnc is True and scrap_production):
# 制造订单报废/返工也需重新编程
if (is_fetchcnc is True and scrap_production is False) or (
is_fetchcnc is False and scrap_production is False):
production.fetchCNC(', '.join(product_id_to_production_names[production.product_id.id]),
scrap_production)
else:
production.write({'programming_no': production_programming.programming_no,
'programming_state': '编程中'})
@@ -404,6 +409,12 @@ class MrpProduction(models.Model):
workorders_values.append(
self.env['mrp.workorder'].json_workorder_str('', production, route))
production.workorder_ids = workorders_values
if production_programming.programming_state == '已编程':
logging.info("production_programming: %s" % production_programming.name)
production.workorder_ids.filtered(lambda t: t.routing_type == 'CNC加工').write({
'cnc_ids': production_programming.workorder_ids.filtered(
lambda
t1: t1.routing_type == 'CNC加工').cnc_ids})
for workorder in production.workorder_ids:
workorder.duration_expected = workorder._get_duration_expected()
@@ -546,8 +557,8 @@ class MrpProduction(models.Model):
# work.button_finish()
# 创建工单并进行排序
def _create_workorder(self):
self._create_workorder3()
def _create_workorder(self, is_fetchcnc=False, scrap_production=False):
self._create_workorder3(is_fetchcnc=is_fetchcnc, scrap_production=scrap_production)
self._reset_work_order_sequence()
return True

View File

@@ -684,7 +684,7 @@ class ResMrpWorkOrder(models.Model):
values)
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
productions._create_workorder()
productions._create_workorder(is_fetchcnc=self.is_fetchcnc, scrap_production=self.production_id)
productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
(
p.move_dest_ids.procure_method != 'make_to_order' and
@@ -996,15 +996,15 @@ class ResMrpWorkOrder(models.Model):
record.write({
'date_planned_finished': tem_date_planned_finished # 保持原值
})
# if record.routing_type == 'CNC加工':
# record.write({
# 'date_finished': tem_date_finished # 保持原值
# })
# if record.routing_type == 'CNC加工' and record.test_results in ['返工', '报废']:
# record.production_id.action_cancel()
# record.production_id.workorder_ids.write({'rfid_code': False, 'rfid_code_old': record.rfid_code})
# if record.is_remanufacture is True:
# record.recreateManufacturingOrWorkerOrder()
if record.routing_type == 'CNC加工':
record.write({
'date_finished': tem_date_finished # 保持原值
})
if record.routing_type == 'CNC加工' and record.test_results in ['返工', '报废']:
record.production_id.action_cancel()
record.production_id.workorder_ids.write({'rfid_code': False, 'rfid_code_old': record.rfid_code})
if record.is_remanufacture is True:
record.recreateManufacturingOrWorkerOrder()
is_production_id = True
for workorder in record.production_id.workorder_ids:
if workorder.state != 'done':

View File

@@ -50,8 +50,8 @@ class ResProductMo(models.Model):
cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', string='刀具物料')
cutting_tool_type = fields.Char(string="刀具物料类型", related='cutting_tool_material_id.name', store=True)
cutting_tool_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='型号名称')
specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='物料号')
cutting_tool_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='型号')
specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='规格')
cutting_tool_type_id = fields.Many2one('sf.cutting.tool.type', string='类型',
domain="[('cutting_tool_material_id.name', '=', cutting_tool_type)]")
@@ -104,15 +104,6 @@ class ResProductMo(models.Model):
compaction_way_id = fields.Many2one('maintenance.equipment.image',
'压紧方式', domain=[('type', '=', '压紧方式')])
name = fields.Char('产品名称', compute='_compute_tool_name', store=True, required=False)
@api.depends('cutting_tool_model_id', 'specification_id')
def _compute_tool_name(self):
for item in self:
if item.cutting_tool_model_id and item.specification_id:
name = '%s%s' % (item.cutting_tool_model_id.name, item.specification_id.name)
item.name = name
@api.onchange('cutting_tool_model_id')
def _onchange_cutting_tool_model_id(self):
for item in self:
@@ -636,7 +627,7 @@ class ResProductMo(models.Model):
'model_remark': item['remark'],
'default_code': '%s-%s' % (order_number, i),
'manual_quotation': item['manual_quotation'] or False,
'part_number': item.get('part_number') or '',
'part_number': item['part_number'] or '',
'active': True,
}
copy_product_id.sudo().write(vals)
@@ -732,10 +723,6 @@ class ResProductMo(models.Model):
logging.info('create-model_file:%s' % len(vals['model_file']))
self._sanitize_vals(vals)
templates = super(ResProductMo, self).create(vals_list)
# 产品名称唯一性校验
for item in templates:
if len(self.search([('name', '=', item.name)])) > 1:
raise ValidationError('产品名称【%s】已存在' % item.name)
if "create_product_product" not in self._context:
templates._create_variant_ids()

View File

@@ -3,7 +3,6 @@ import base64
import qrcode
from collections import defaultdict, namedtuple
import logging
import io
import json
from re import split as regex_split
from re import findall as regex_findall
@@ -208,7 +207,7 @@ class StockRule(models.Model):
'''
创建工单
'''
productions._create_workorder()
productions._create_workorder(is_fetchcnc=False, scrap_production=False)
productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
(
@@ -669,14 +668,12 @@ class ReStockMove(models.Model):
else:
view = self.env.ref('stock.view_stock_move_nosuggest_operations')
if self.state == "assigned":
if self.product_id.tracking == "serial":
if self.product_id.categ_id.name == '刀具':
self.next_serial = self._get_tool_next_serial(self.company_id, self.product_id, self.origin)
else:
self.next_serial = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id)
elif self.product_id.tracking == "lot":
self._put_tool_lot(self.company_id, self.product_id, self.origin)
if self.product_id.tracking == "serial" and self.state == "assigned":
print(self.origin)
if self.product_id.categ_id.name == '刀具':
self.next_serial = self._get_tool_next_serial(self.company_id, self.product_id, self.origin)
else:
self.next_serial = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id)
return {
'name': _('Detailed Operations'),
@@ -701,35 +698,6 @@ class ReStockMove(models.Model):
),
}
def _put_tool_lot(self, company, product, origin):
if product.tracking == "lot" and self.product_id.categ_id.name == '刀具':
if not self.move_line_nosuggest_ids:
lot_names = self.env['stock.lot'].generate_lot_names(
'%s-%s-%s' % ('%s-T-DJWL-%s' % (
product.cutting_tool_model_id.code.split('-')[0], product.cutting_tool_material_id.code),
datetime.now().strftime("%Y%m%d"), origin), 1)
move_lines_commands = self._generate_serial_move_line_commands_tool_lot(lot_names)
self.write({'move_line_nosuggest_ids': move_lines_commands})
for item in self.move_line_nosuggest_ids:
if item.lot_name:
item.lot_qr_code = self.compute_lot_qr_code(item.lot_name)
def compute_lot_qr_code(self, lot_name):
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(lot_name)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
buffer = io.BytesIO()
img.save(buffer, format="PNG")
binary_data = buffer.getvalue()
data = base64.b64encode(binary_data).decode() # 确保返回的是字符串形式的数据
return data
def _get_tool_next_serial(self, company, product, origin):
"""Return the next serial number to be attributed to the product."""
if product.tracking == "serial":
@@ -743,67 +711,6 @@ class ReStockMove(models.Model):
else:
return "%s-T-%s-%s-%03d" % (split_codes[0], origin, product.specification_id.name, 1)
def _generate_serial_move_line_commands_tool_lot(self, lot_names, origin_move_line=None):
"""Return a list of commands to update the move lines (write on
existing ones or create new ones).
Called when user want to create and assign multiple serial numbers in
one time (using the button/wizard or copy-paste a list in the field).
:param lot_names: A list containing all serial number to assign.
:type lot_names: list
:param origin_move_line: A move line to duplicate the value from, default to None
:type origin_move_line: record of :class:`stock.move.line`
:return: A list of commands to create/update :class:`stock.move.line`
:rtype: list
"""
self.ensure_one()
# Select the right move lines depending of the picking type configuration.
move_lines = self.env['stock.move.line']
if self.picking_type_id.show_reserved:
move_lines = self.move_line_ids.filtered(lambda ml: not ml.lot_id and not ml.lot_name)
else:
move_lines = self.move_line_nosuggest_ids.filtered(lambda ml: not ml.lot_id and not ml.lot_name)
loc_dest = origin_move_line and origin_move_line.location_dest_id
move_line_vals = {
'picking_id': self.picking_id.id,
'location_id': self.location_id.id,
'product_id': self.product_id.id,
'product_uom_id': self.product_id.uom_id.id,
'qty_done': self.product_uom_qty,
}
if origin_move_line:
# `owner_id` and `package_id` are taken only in the case we create
# new move lines from an existing move line. Also, updates the
# `qty_done` because it could be usefull for products tracked by lot.
move_line_vals.update({
'owner_id': origin_move_line.owner_id.id,
'package_id': origin_move_line.package_id.id,
'qty_done': origin_move_line.qty_done or 1,
})
move_lines_commands = []
qty_by_location = defaultdict(float)
for lot_name in lot_names:
# We write the lot name on an existing move line (if we have still one)...
if move_lines:
move_lines_commands.append((1, move_lines[0].id, {
'lot_name': lot_name,
'qty_done': 1,
}))
qty_by_location[move_lines[0].location_dest_id.id] += 1
move_lines = move_lines[1:]
# ... or create a new move line with the serial name.
else:
loc = loc_dest or self.location_dest_id._get_putaway_strategy(self.product_id, quantity=1,
packaging=self.product_packaging_id,
additional_qty=qty_by_location)
move_line_cmd = dict(move_line_vals, lot_name=lot_name, location_dest_id=loc.id)
move_lines_commands.append((0, 0, move_line_cmd))
qty_by_location[loc.id] += 1
return move_lines_commands
class ReStockQuant(models.Model):
_inherit = 'stock.quant'

View File

@@ -477,13 +477,13 @@
<page string="后置三元检测" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
<group>
<field name="test_results" attrs='{"invisible":[("results","!=",False)]}'/>
<!-- <field name="is_remanufacture" attrs='{"invisible":[("test_results","!=","报废")]}'/>-->
<!-- <field name="is_fetchcnc"-->
<!-- attrs='{"invisible":["|",("test_results","=","合格"),("is_remanufacture","=",False)]}'/>-->
<!-- <field name="reason"-->
<!-- attrs='{"required":[("test_results","!=","合格")],"invisible":[("test_results","=","合格")]}'/>-->
<!-- <field name="detailed_reason" attrs='{"invisible":[("test_results","=","合格")]}'/>-->
<!-- <field name="results" readonly="1" attrs='{"invisible":[("results","!=","合格")]}'/>-->
<field name="is_remanufacture" attrs='{"invisible":[("test_results","!=","报废")]}'/>
<field name="is_fetchcnc"
attrs='{"invisible":["|",("test_results","=","合格"),("is_remanufacture","=",False)]}'/>
<field name="reason"
attrs='{"required":[("test_results","!=","合格")],"invisible":[("test_results","=","合格")]}'/>
<field name="detailed_reason" attrs='{"invisible":[("test_results","=","合格")]}'/>
<field name="results" readonly="1" attrs='{"invisible":[("results","!=","合格")]}'/>
<field name="detection_report" attrs='{"invisible":[("results","!=",False)]}'
widget="pdf_viewer"/>
</group>

View File

@@ -26,7 +26,6 @@ class ResConfigSettings(models.TransientModel):
ftp_port = fields.Char(string='FTP端口')
ftp_user = fields.Char(string='FTP用户')
ftp_password = fields.Char(string='FTP密码')
enable_tool_presetter = fields.Boolean('是否启用刀具预调仪', default=True)
def sf_all_sync(self):
try:
@@ -109,7 +108,6 @@ class ResConfigSettings(models.TransientModel):
ftp_port = config.get_param('ftp_port', default='')
ftp_user = config.get_param('ftp_user', default='')
ftp_password = config.get_param('ftp_password', default='')
enable_tool_presetter = config.get_param('enable_tool_presetter', default='')
values.update(
token=token,
@@ -123,8 +121,7 @@ class ResConfigSettings(models.TransientModel):
ftp_host=ftp_host,
ftp_port=ftp_port,
ftp_user=ftp_user,
ftp_password=ftp_password,
enable_tool_presetter=enable_tool_presetter
ftp_password=ftp_password
)
return values
@@ -143,4 +140,3 @@ class ResConfigSettings(models.TransientModel):
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 "")
ir_config.set_param("enable_tool_presetter", self.enable_tool_presetter or False)

View File

@@ -114,21 +114,6 @@
</div>
</div>
</div>
<div>
<h2>刀具预调仪配置</h2>
<div class="row mt16 o_settings_container">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="enable_tool_presetter"/>
</div>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="enable_tool_presetter" string="是否启用刀具预调仪"/>
</div>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>

View File

@@ -233,12 +233,12 @@ class ResPartnerToSale(models.Model):
if obj:
raise UserError('该税ID已存在,请重新输入')
# @api.constrains('email')
# def _check_email(self):
# if self.customer_rank > 0:
# obj = self.sudo().search([('email', '=', self.email), ('id', '!=', self.id), ('active', '=', True)])
# if obj:
# raise UserError('该邮箱已存在,请重新输入')
@api.constrains('email')
def _check_email(self):
if self.customer_rank > 0:
obj = self.sudo().search([('email', '=', self.email), ('id', '!=', self.id), ('active', '=', True)])
if obj:
raise UserError('该邮箱已存在,请重新输入')
@api.model
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):

View File

@@ -24,18 +24,18 @@
<attribute name="required">1</attribute>
<attribute name="attrs">{'readonly': [('id','!=', False)]}</attribute>
</field>
<!-- <field name="email" position="replace">-->
<!-- <field name="email"-->
<!-- attrs="{'readonly': [('id','!=', False)]}"/>-->
<!-- </field>-->
<!-- <field name="mobile" position="attributes">-->
<!-- <attribute name="attrs">{'required': [('phone', '=', False)],'readonly': [('id','!=', False)]}-->
<!-- </attribute>-->
<!-- </field>-->
<!-- <field name="phone" position="attributes">-->
<!-- <attribute name="attrs">{'required': [('mobile', '=', False)],'readonly': [('id','!=', False)]}-->
<!-- </attribute>-->
<!-- </field>-->
<field name="email" position="replace">
<field name="email"
attrs="{'readonly': [('id','!=', False)]}"/>
</field>
<field name="mobile" position="attributes">
<attribute name="attrs">{'required': [('phone', '=', False)],'readonly': [('id','!=', False)]}
</attribute>
</field>
<field name="phone" position="attributes">
<attribute name="attrs">{'required': [('mobile', '=', False)],'readonly': [('id','!=', False)]}
</attribute>
</field>
<field name="street" position="attributes">
<attribute name="attrs">{'readonly': [('id','!=', False)]}
</attribute>
@@ -56,10 +56,10 @@
<field name="user_id" widget="many2one_avatar_user" context="{'is_sale': True }"
attrs="{'required' : [('customer_rank','>', 0)]}"/>
</xpath>
<!-- <field name="category_id" position="attributes">-->
<!-- <attribute name="required">1</attribute>-->
<!-- <attribute name="attrs">{'readonly': [('id','!=', False)]}</attribute>-->
<!-- </field>-->
<field name="category_id" position="attributes">
<attribute name="required">1</attribute>
<attribute name="attrs">{'readonly': [('id','!=', False)]}</attribute>
</field>
<field name="company_registry" position="attributes">
<attribute name="attrs">{'readonly': [('id','!=', False)]}</attribute>
</field>
@@ -101,7 +101,7 @@
<field name="property_supplier_payment_term_id" position="before">
<field name="purchase_user_id" context="{'supplier_rank': supplier_rank }"
widget="many2one_avatar_user"
attrs="{'required' : [('supplier_rank','>', 0)]}"/>
attrs="{'required' : [('supplier_rank','>', 0)],'readonly': [('customer_rank','>', 0)]}"/>
</field>
<xpath expr="//field[@name='property_account_position_id']" position="attributes">
<attribute name="attrs">{'readonly': [('id','!=', False)]}</attribute>
@@ -195,10 +195,10 @@
<attribute name="attrs">{'invisible': [('customer_rank','=', 0)]}
</attribute>
</field>
<!-- <field name="user_id" position="before">-->
<!-- <field name="purchase_user_id" widget="many2one_avatar_user"-->
<!-- attrs="{'invisible' : [('supplier_rank','=', 0)]}"/>-->
<!-- </field>-->
<field name="user_id" position="before">
<field name="purchase_user_id" widget="many2one_avatar_user"
attrs="{'invisible' : [('supplier_rank','=', 0)]}"/>
</field>
</field>
</record>
</data>

View File

@@ -1,6 +1,54 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<record id="sale_order_view_search_inherit_sf" model="ir.ui.view">
<field name="name">sale.order.search.inherit.sf</field>
<field name="model">sale.order</field>
<field name="mode">primary</field>
<field name="inherit_id" ref="sale.view_sales_order_filter"/>
<field name="arch" type="xml">
<filter name="my_sale_orders_filter" position="replace">
<field name="campaign_id"/>
<separator/>
<filter string="报价" name="draft" domain="[('state','in',('draft', 'sent'))]"/>
<filter string="销售订单" name="sales" domain="[('state','in',('sale','done'))]"/>
<separator/>
<filter string="创建日期" name="filter_create_date" date="create_date"/>
</filter>
</field>
</record>
<record id="action_quotations_with_onboarding_inherit_sf" model="ir.actions.act_window">
<field name="name">报价</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sale.order</field>
<field name="view_id" ref="sale.view_quotation_tree_with_onboarding"/>
<field name="view_mode">tree,kanban,form,calendar,pivot,graph,activity</field>
<field name="search_view_id" ref="sale_order_view_search_inherit_sf"/>
<field name="context">{'search_default_my_quotation': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new quotation, the first step of a new sale!
</p>
<p>
Once the quotation is confirmed by the customer, it becomes a sales order.
<br/>
You will be able to create an invoice and collect the payment.
</p>
</field>
</record>
<!-- <menuitem id="menu_sale_quotations">-->
<!-- <field name="active" eval="False"/>-->
<!-- </menuitem>-->
<menuitem id="menu_sale_quotations_inherit_sf"
action="action_quotations_with_onboarding_inherit_sf"
groups="sales_team.group_sale_salesman,sf_base.group_sale_salemanager,sf_base.group_sale_director"
parent="sale.sale_order_menu"
sequence="11"/>
<record model="ir.ui.view" id="view_sale_order_form_inherit_sf">
<field name="name">sale.order.form.inherit.sf</field>
<field name="model">sale.order</field>

View File

@@ -22,7 +22,6 @@
'views/tool_material_search.xml',
'views/fixture_material_search_views.xml',
'views/menu_view.xml',
'views/stock.xml',
'data/tool_data.xml',
],
'demo': [

View File

@@ -109,7 +109,6 @@ class Manufacturing_Connect(http.Controller):
res = {'Succeed': True, 'Datas': []}
try:
datas = request.httprequest.data
logging.info('datas: %s' % datas)
ret = str(datas, 'utf-8')
data_lists = ret.split(",")
data_list = [data.replace('+', '') for data in data_lists]
@@ -127,4 +126,4 @@ class Manufacturing_Connect(http.Controller):
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('put_tool_preset_parameter_port error:%s' % e)
return json.JSONEncoder().encode(res)
return json.JSONEncoder().encode(res)

View File

@@ -7,5 +7,4 @@ from . import functional_tool_enroll
from . import fixture_material_search
from . import fixture_enroll
from . import temporary_data_processing_methods
from . import stock

View File

@@ -181,7 +181,6 @@ class MachineTableToolChangingApply(models.Model):
class CAMWorkOrderProgramKnifePlan(models.Model):
_name = 'sf.cam.work.order.program.knife.plan'
_inherit = ['mail.thread']
_description = 'CAM工单程序用刀计划'
name = fields.Char('工单任务编号')
@@ -229,7 +228,7 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
estimated_processing_time = fields.Char('预计加工时间')
plan_execute_status = fields.Selection([('0', '待下发'), ('1', '执行中'), ('2', '已完成')],
string='计划执行状态', default='0', readonly=False, tracking=True)
string='计划执行状态', default='0', readonly=False)
sf_functional_tool_assembly_id = fields.Many2one('sf.functional.tool.assembly', '功能刀具组装', readonly=True)
@@ -283,8 +282,7 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
'loading_task_source': '0',
'applicant': self.env.user.name,
'use_tool_time': fields.Datetime.now() + timedelta(
hours=4) if not self.need_knife_time else self.need_knife_time,
'use_tool_time': self.need_knife_time,
'reason_for_applying': '工单用刀',
'sf_cam_work_order_program_knife_plan_id': self.id
@@ -364,7 +362,6 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
class FunctionalToolAssembly(models.Model):
_name = 'sf.functional.tool.assembly'
_inherit = ['mail.thread']
_description = '功能刀具组装'
_order = 'assemble_status, use_tool_time asc'
@@ -399,7 +396,7 @@ class FunctionalToolAssembly(models.Model):
applicant = fields.Char(string='申请人', readonly=True)
apply_time = fields.Datetime(string='申请时间', default=fields.Datetime.now(), readonly=True)
assemble_status = fields.Selection([('0', '待组装'), ('1', '已组装')], string='组装状态', default='0',
tracking=True, readonly=True)
readonly=True)
cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', readonly=True)
whether_standard_knife = fields.Boolean(string='是否标准刀', default=True, readonly=True)
reason_for_applying = fields.Char(string='申请原因', readonly=True)
@@ -416,9 +413,8 @@ class FunctionalToolAssembly(models.Model):
return categories.browse(functional_tool_type_ids)
# 刀具物料信息
# ==============整体式刀具型号=============
integral_freight_barcode_id = fields.Many2one('sf.shelf.location', string='整体式刀具货位')
integral_lot_id = fields.Many2one('stock.lot', string='整体式刀具批次')
# ==============整体式刀具型号============
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='整体式刀具型号',
@@ -428,15 +424,19 @@ class FunctionalToolAssembly(models.Model):
sf_tool_brand_id_1 = fields.Many2one('sf.machine.brand', string='整体式刀具品牌',
related='integral_product_id.brand_id')
@api.depends('integral_lot_id')
@api.depends('integral_freight_barcode')
def _compute_integral_product_id(self):
for item in self:
if item.integral_lot_id:
item.integral_product_id = item.integral_lot_id.product_id.id
if item.integral_freight_barcode:
location = self.env['sf.shelf.location'].sudo().search(
[('barcode', '=', item.integral_freight_barcode)])
if location:
item.integral_product_id = location.product_id.id
else:
item.integral_product_id = False
# =================刀片型号=============
blade_freight_barcode_id = fields.Many2one('sf.shelf.location', string='刀片货位')
blade_lot_id = fields.Many2one('stock.lot', string='刀片批次')
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='刀片型号',
@@ -445,15 +445,18 @@ class FunctionalToolAssembly(models.Model):
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_lot_id')
@api.depends('blade_freight_barcode')
def _compute_blade_product_id(self):
for item in self:
if item.blade_lot_id:
item.blade_product_id = item.blade_lot_id.product_id.id
if item.blade_freight_barcode:
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.blade_freight_barcode)])
if location:
item.blade_product_id = location.product_id.id
else:
item.blade_product_id = False
# ==============刀杆型号================
bar_freight_barcode_id = fields.Many2one('sf.shelf.location', string='刀杆货位')
bar_lot_id = fields.Many2one('stock.lot', string='刀杆批次')
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='刀杆型号',
@@ -462,15 +465,18 @@ class FunctionalToolAssembly(models.Model):
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_lot_id')
@api.depends('bar_freight_barcode')
def _compute_bar_product_id(self):
for item in self:
if item.bar_lot_id:
item.bar_product_id = item.bar_lot_id.product_id.id
if item.bar_freight_barcode:
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.bar_freight_barcode)])
if location:
item.bar_product_id = location.product_id.id
else:
item.bar_product_id = False
# =============刀盘型号================
pad_freight_barcode_id = fields.Many2one('sf.shelf.location', string='刀盘货位')
pad_lot_id = fields.Many2one('stock.lot', string='刀盘批次')
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='刀盘型号',
@@ -479,11 +485,15 @@ class FunctionalToolAssembly(models.Model):
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_lot_id')
@api.depends('pad_freight_barcode')
def _compute_pad_product_id(self):
for item in self:
if item.pad_lot_id:
item.pad_product_id = item.pad_lot_id.product_id.id
if item.pad_freight_barcode:
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.pad_freight_barcode)])
if location:
item.pad_product_id = location.product_id.id
else:
item.pad_product_id = False
# ==============刀柄型号==============
handle_freight_rfid = fields.Char('刀柄Rfid', compute='_compute_handle_product_id', store=True)
@@ -507,8 +517,7 @@ class FunctionalToolAssembly(models.Model):
item.handle_freight_rfid = False
# ==============夹头型号==============
chuck_freight_barcode_id = fields.Many2one('sf.shelf.location', string='夹头货位')
chuck_lot_id = fields.Many2one('stock.lot', string='夹头批次')
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='夹头型号',
@@ -517,18 +526,17 @@ class FunctionalToolAssembly(models.Model):
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_lot_id')
@api.depends('chuck_freight_barcode')
def _compute_chuck_product_id(self):
for item in self:
if item.chuck_lot_id:
item.chuck_product_id = item.chuck_lot_id.product_id.id
if item.chuck_freight_barcode:
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.chuck_freight_barcode)])
if location:
item.chuck_product_id = location.product_id.id
else:
item.chuck_product_id = False
# ==================待删除字段==================
integral_freight_barcode = fields.Char('整体式刀具货位')
blade_freight_barcode = fields.Char('刀片货位')
bar_freight_barcode = fields.Char('刀杆货位')
pad_freight_barcode = fields.Char('刀盘货位')
chuck_freight_barcode = fields.Char('夹头货位')
blade_name = fields.Char('')
integral_name = fields.Char('')
blade_code_id = fields.Many2one('stock.lot', '刀片序列号')
@@ -671,7 +679,7 @@ class FunctionalToolAssembly(models.Model):
class FunctionalToolDismantle(models.Model):
_name = 'sf.functional.tool.dismantle'
_inherit = ["barcodes.barcode_events_mixin", 'mail.thread']
_inherit = ["barcodes.barcode_events_mixin"]
_description = '功能刀具拆解'
def on_barcode_scanned(self, barcode):
@@ -732,22 +740,6 @@ class FunctionalToolDismantle(models.Model):
raise ValidationError('该功能刀具因为%s拆解,无需录入库位' % self.dismantle_cause)
name = fields.Char('名称', related='functional_tool_id.name')
code = fields.Char('拆解单号', default=lambda self: self._get_code(), readonly=True)
def _get_code(self):
"""
自动生成拆解单编码
"""
new_time = str(fields.Date.today())
datetime = new_time[2:4] + new_time[5:7] + new_time[-2:]
functional_tool_dismantle = self.env['sf.functional.tool.dismantle'].sudo().search(
[('code', 'ilike', datetime)], limit=1, order="id desc")
if not functional_tool_dismantle:
num = "%03d" % 1
else:
m = int(functional_tool_dismantle.code[-3:]) + 1
num = "%03d" % m
return 'GNDJ-CJD-%s-%s' % (datetime, num)
functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True,
domain=[('functional_tool_status', '!=', '已拆除')])
@@ -761,7 +753,7 @@ class FunctionalToolDismantle(models.Model):
dismantle_cause = fields.Selection(
[('寿命到期报废', '寿命到期报废'), ('崩刀报废', '崩刀报废'), ('更换为其他刀具', '更换为其他刀具'),
('刀具需磨削', '刀具需磨削')], string='拆解原因', required=True, tracking=True)
('刀具需磨削', '刀具需磨削')], string='拆解原因', required=True)
dismantle_data = fields.Datetime('拆解日期', readonly=True)
dismantle_person = fields.Char('拆解人', readonly=True)
image = fields.Binary('图片', readonly=True)
@@ -769,7 +761,7 @@ class FunctionalToolDismantle(models.Model):
scrap_id = fields.Char('报废单号', readonly=True)
grinding_id = fields.Char('磨削单号', readonly=True)
state = fields.Selection([('待拆解', '待拆解'), ('已拆解', '已拆解')], default='待拆解', tracking=True)
state = fields.Selection([('待拆解', '待拆解'), ('已拆解', '已拆解')], default='待拆解')
active = fields.Boolean('有效', default=True)
# 刀柄
@@ -779,9 +771,7 @@ class FunctionalToolDismantle(models.Model):
related='handle_product_id.cutting_tool_model_id')
handle_brand_id = fields.Many2one('sf.machine.brand', string='刀柄品牌', related='handle_product_id.brand_id')
handle_rfid = fields.Char(string='刀柄Rfid', compute='_compute_functional_tool_num', store=True)
handle_lot_id = fields.Many2one('stock.lot', string='刀柄序列号', compute='_compute_functional_tool_num',
store=True)
scrap_boolean = fields.Boolean(string='刀柄是否报废', default=False, tracking=True)
scrap_boolean = fields.Boolean(string='刀柄是否报废', default=False)
# 整体式
integral_product_id = fields.Many2one('product.product', string='整体式刀具',
@@ -790,8 +780,6 @@ class FunctionalToolDismantle(models.Model):
related='integral_product_id.cutting_tool_model_id')
integral_brand_id = fields.Many2one('sf.machine.brand', string='整体式刀具品牌',
related='integral_product_id.brand_id')
integral_lot_id = fields.Many2one('stock.lot', string='整体式刀具批次', compute='_compute_functional_tool_num',
store=True)
integral_freight_id = fields.Many2one('sf.shelf.location', '整体式刀具目标货位',
domain="[('product_id', 'in', (integral_product_id, False))]")
@@ -801,7 +789,6 @@ class FunctionalToolDismantle(models.Model):
blade_type_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀片型号',
related='blade_product_id.cutting_tool_model_id')
blade_brand_id = fields.Many2one('sf.machine.brand', string='刀片品牌', related='blade_product_id.brand_id')
blade_lot_id = fields.Many2one('stock.lot', string='刀片批次', compute='_compute_functional_tool_num', store=True)
blade_freight_id = fields.Many2one('sf.shelf.location', '刀片目标货位',
domain="[('product_id', 'in', (blade_product_id, False))]")
@@ -811,7 +798,6 @@ class FunctionalToolDismantle(models.Model):
bar_type_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀杆型号',
related='bar_product_id.cutting_tool_model_id')
bar_brand_id = fields.Many2one('sf.machine.brand', string='刀杆品牌', related='bar_product_id.brand_id')
bar_lot_id = fields.Many2one('stock.lot', string='刀杆批次', compute='_compute_functional_tool_num', store=True)
bar_freight_id = fields.Many2one('sf.shelf.location', '刀杆目标货位',
domain="[('product_id', 'in', (bar_product_id, False))]")
@@ -821,7 +807,6 @@ class FunctionalToolDismantle(models.Model):
pad_type_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀盘型号',
related='pad_product_id.cutting_tool_model_id')
pad_brand_id = fields.Many2one('sf.machine.brand', string='刀盘品牌', related='pad_product_id.brand_id')
pad_lot_id = fields.Many2one('stock.lot', string='刀盘批次', compute='_compute_functional_tool_num', store=True)
pad_freight_id = fields.Many2one('sf.shelf.location', '刀盘目标货位',
domain="[('product_id', 'in', (pad_product_id, False))]")
@@ -831,7 +816,6 @@ class FunctionalToolDismantle(models.Model):
chuck_type_id = fields.Many2one('sf.cutting_tool.standard.library', string='夹头型号',
related='chuck_product_id.cutting_tool_model_id')
chuck_brand_id = fields.Many2one('sf.machine.brand', string='夹头品牌', related='chuck_product_id.brand_id')
chuck_lot_id = fields.Many2one('stock.lot', string='夹头批次', compute='_compute_functional_tool_num', store=True)
chuck_freight_id = fields.Many2one('sf.shelf.location', '夹头目标货位',
domain="[('product_id', 'in', (chuck_product_id, False))]")
@@ -855,20 +839,12 @@ class FunctionalToolDismantle(models.Model):
item.rfid = item.functional_tool_id.rfid
item.handle_rfid = item.functional_tool_id.rfid
# 产品
item.handle_product_id = item.functional_tool_id.functional_tool_name_id.handle_product_id.id
item.integral_product_id = item.functional_tool_id.functional_tool_name_id.integral_product_id.id
item.blade_product_id = item.functional_tool_id.functional_tool_name_id.blade_product_id.id
item.bar_product_id = item.functional_tool_id.functional_tool_name_id.bar_product_id.id
item.pad_product_id = item.functional_tool_id.functional_tool_name_id.pad_product_id.id
item.chuck_product_id = item.functional_tool_id.functional_tool_name_id.chuck_product_id.id
# 批次/序列号
item.handle_lot_id = item.functional_tool_id.functional_tool_name_id.handle_code_id.id
item.integral_lot_id = item.functional_tool_id.functional_tool_name_id.integral_lot_id.id
item.blade_lot_id = item.functional_tool_id.functional_tool_name_id.blade_lot_id.id
item.bar_lot_id = item.functional_tool_id.functional_tool_name_id.bar_lot_id.id
item.pad_lot_id = item.functional_tool_id.functional_tool_name_id.pad_lot_id.id
item.chuck_lot_id = item.functional_tool_id.functional_tool_name_id.chuck_lot_id.id
else:
item.tool_groups_id = False
item.tool_type_id = False
@@ -884,45 +860,14 @@ class FunctionalToolDismantle(models.Model):
item.pad_product_id = False
item.chuck_product_id = False
item.handle_lot_id = False
item.integral_lot_id = False
item.blade_lot_id = False
item.bar_lot_id = False
item.pad_lot_id = False
item.chuck_lot_id = False
def location_duplicate_check(self):
"""
目标货位去重校验
"""
if self.blade_freight_id:
if self.bar_freight_id:
if self.blade_freight_id == self.bar_freight_id:
raise ValidationError('【刀片】和【刀杆】的目标货位重复,请重新选择!')
elif self.pad_freight_id:
if self.blade_freight_id == self.pad_freight_id:
raise ValidationError('【刀片】和【刀盘】的目标货位重复,请重新选择!')
if self.chuck_freight_id:
if self.chuck_freight_id == self.integral_freight_id:
raise ValidationError('【夹头】和【整体式刀具】的目标货位重复,请重新选择!')
if self.chuck_freight_id == self.blade_freight_id:
raise ValidationError('【夹头】和【刀片】的目标货位重复,请重新选择!')
if self.chuck_freight_id == self.bar_freight_id:
raise ValidationError('【夹头】和【刀杆】的目标货位重复,请重新选择!')
if self.chuck_freight_id == self.pad_freight_id:
raise ValidationError('【夹头】和【刀盘】的目标货位重复,请重新选择!')
def confirmation_disassembly(self):
logging.info('%s刀具确认开始拆解' % self.dismantle_cause)
code = self.code
if self.functional_tool_id.functional_tool_status == '已拆除':
raise ValidationError('Rfid为【%s】的功能刀具已经拆解,请勿重复操作!' % self.functional_tool_id.rfid_dismantle)
# 对拆解的功能刀具进行校验,只有在刀具房的功能刀具才能拆解
if self.functional_tool_id.tool_room_num == 0:
raise ValidationError('Rfid为【%s】的功能刀具当前位置为【%s】,不能进行拆解!' % (
self.rfid, self.functional_tool_id.current_location))
# 目标重复校验
self.location_duplicate_check()
location = self.env['stock.location'].search([('name', '=', '刀具组装位置')])
location_dest = self.env['stock.location'].search([('name', '=', '刀具房')])
# =================刀柄是否[报废]拆解=======
@@ -934,62 +879,53 @@ class FunctionalToolDismantle(models.Model):
functional_tool_assembly = self.functional_tool_id.functional_tool_name_id
if self.scrap_boolean:
# 刀柄报废 入库到Scrap
lot.create_stock_quant(location, location_dest_scrap, functional_tool_assembly.id, code,
lot.create_stock_quant(location, location_dest_scrap, functional_tool_assembly.id, '功能刀具拆解',
functional_tool_assembly, functional_tool_assembly.tool_groups_id)
else:
# 刀柄不报废 入库到刀具房
lot.create_stock_quant(location, location_dest, functional_tool_assembly.id, code,
lot.create_stock_quant(location, location_dest, functional_tool_assembly.id, '功能刀具拆解',
functional_tool_assembly, functional_tool_assembly.tool_groups_id)
# ==============功能刀具[报废]拆解================
if self.dismantle_cause in ['寿命到期报废', '崩刀报废']:
# 除刀柄外物料报废 入库到Scrap
if self.integral_product_id:
self.integral_product_id.dismantle_stock_moves(False, self.integral_lot_id, location,
location_dest_scrap, code)
self.integral_product_id.dismantle_stock_moves(False, location, location_dest_scrap)
elif self.blade_product_id:
self.blade_product_id.dismantle_stock_moves(False, self.blade_lot_id, location, location_dest_scrap,
code)
self.blade_product_id.dismantle_stock_moves(False, location, location_dest_scrap)
if self.bar_product_id:
self.bar_product_id.dismantle_stock_moves(False, self.bar_lot_id, location, location_dest_scrap,
code)
self.bar_product_id.dismantle_stock_moves(False, location, location_dest_scrap)
elif self.pad_product_id:
self.pad_product_id.dismantle_stock_moves(False, self.pad_lot_id, location, location_dest_scrap,
code)
self.pad_product_id.dismantle_stock_moves(False, location, location_dest_scrap)
if self.chuck_product_id:
self.chuck_product_id.dismantle_stock_moves(False, self.chuck_lot_id, location, location_dest_scrap,
code)
self.chuck_product_id.dismantle_stock_moves(False, location, location_dest_scrap)
# ===========功能刀具[磨削]拆解==============
# elif self.dismantle_cause in ['刀具需磨削']:
# location_dest = self.env['stock.location'].search([('name', '=', '磨削房')])
# # 除刀柄外物料拆解 入库到具体库位
# if self.integral_product_id:
# self.integral_product_id.dismantle_stock_moves(False, location, location_dest)
# elif self.blade_product_id:
# self.blade_product_id.dismantle_stock_moves(False, location, location_dest)
# if self.bar_product_id:
# self.bar_product_id.dismantle_stock_moves(False, location, location_dest)
# elif self.pad_product_id:
# self.pad_product_id.dismantle_stock_moves(False, location, location_dest)
# if self.chuck_product_id:
# self.chuck_product_id.dismantle_stock_moves(False, location, location_dest)
# ==============功能刀具[更换,磨削]拆解==============
elif self.dismantle_cause in ['更换为其他刀具', '刀具需磨削']:
# 除刀柄外物料拆解 入库到具体
elif self.dismantle_cause in ['刀具需磨削']:
location_dest = self.env['stock.location'].search([('name', '=', '磨削房')])
# 除刀柄外物料拆解 入库到具体库位
if self.integral_product_id:
self.integral_product_id.dismantle_stock_moves(False, location, location_dest)
elif self.blade_product_id:
self.blade_product_id.dismantle_stock_moves(False, location, location_dest)
if self.bar_product_id:
self.bar_product_id.dismantle_stock_moves(False, location, location_dest)
elif self.pad_product_id:
self.pad_product_id.dismantle_stock_moves(False, location, location_dest)
if self.chuck_product_id:
self.chuck_product_id.dismantle_stock_moves(False, location, location_dest)
# ==============功能刀具[更换]拆解==============
elif self.dismantle_cause in ['更换为其他刀具']:
# 除刀柄外物料拆解 入库到具体
if self.integral_freight_id:
self.integral_product_id.dismantle_stock_moves(self.integral_freight_id, self.integral_lot_id, location,
location_dest, code)
self.integral_product_id.dismantle_stock_moves(self.integral_freight_id.barcode, location,
location_dest)
elif self.blade_freight_id:
self.blade_product_id.dismantle_stock_moves(self.blade_freight_id, self.blade_lot_id, location,
location_dest, code)
self.blade_product_id.dismantle_stock_moves(self.blade_freight_id.barcode, location, location_dest)
if self.bar_freight_id:
self.bar_product_id.dismantle_stock_moves(self.bar_freight_id, self.bar_lot_id, location,
location_dest, code)
self.bar_product_id.dismantle_stock_moves(self.bar_freight_id.barcode, location, location_dest)
elif self.pad_freight_id:
self.pad_product_id.dismantle_stock_moves(self.pad_freight_id, self.pad_lot_id, location,
location_dest, code)
self.pad_product_id.dismantle_stock_moves(self.pad_freight_id.barcode, location, location_dest)
if self.chuck_freight_id:
self.chuck_product_id.dismantle_stock_moves(self.chuck_freight_id, self.chuck_lot_id, location,
location_dest, code)
self.chuck_product_id.dismantle_stock_moves(self.chuck_freight_id.barcode, location, location_dest)
# ===============删除功能刀具的Rfid字段的值 赋值给Rfid(已拆解)字段=====
self.functional_tool_id.write({
'rfid_dismantle': self.functional_tool_id.rfid,
@@ -1010,22 +946,26 @@ class FunctionalToolDismantle(models.Model):
class ProductProduct(models.Model):
_inherit = 'product.product'
def dismantle_stock_moves(self, shelf_location_id, lot_id, location_id, location_dest_id, code):
def dismantle_stock_moves(self, shelf_location_barcode, location_id, location_dest_id):
# 创建功能刀具拆解单产品库存移动记录
stock_move_id = self.env['stock.move'].sudo().create({
'name': code,
'name': '功能刀具拆解',
'product_id': self.id,
'location_id': location_id.id,
'location_dest_id': location_dest_id.id,
'product_uom_qty': 1.00,
'state': 'done'
})
if shelf_location_barcode:
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', shelf_location_barcode)])
location.product_num = location.product_num + 1
else:
location = self.env['sf.shelf.location']
# 创建移动历史记录
stock_move_line_id = self.env['stock.move.line'].sudo().create({
'product_id': self.id,
'lot_id': lot_id.id,
'move_id': stock_move_id.id,
'destination_location_id': shelf_location_id.id,
'current_location_id': location.id,
'install_tool_time': fields.Datetime.now(),
'qty_done': 1.0,
'state': 'done',

View File

@@ -14,15 +14,14 @@ class FunctionalCuttingToolEntity(models.Model):
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具组装单', readonly=True)
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id',
store=True)
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id')
code = fields.Char('编码')
rfid = fields.Char('Rfid', readonly=True)
rfid_dismantle = fields.Char('Rfid(已拆解)', readonly=True)
name = fields.Char('名称')
tool_name_id = fields.Many2one('sf.tool.inventory', '功能刀具名称')
sf_cutting_tool_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀具型号')
barcode_id = fields.Many2one('stock.lot', string='序列号', readonly=True)
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)
@@ -31,135 +30,66 @@ class FunctionalCuttingToolEntity(models.Model):
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, digits=(10, 3))
handle_length = fields.Float(string='刀柄长度(mm)', readonly=True, digits=(10, 3))
handle_length = fields.Float(string='刀柄长度(mm)',readonly=True, digits=(10, 3))
functional_tool_length = fields.Float(string='伸出长(mm)', readonly=True, digits=(10, 3))
effective_length = fields.Float(string='有效长(mm)', readonly=True)
tool_room_num = fields.Integer(string='刀具房数量', compute='_compute_num', store=True)
line_edge_knife_library_num = fields.Integer(string='线边刀库数量', compute='_compute_num', store=True)
machine_knife_library_num = fields.Integer(string='机内刀库数量', compute='_compute_num', store=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='当前位置', compute='_compute_current_location_id',
store=True)
current_shelf_location_id = fields.Many2one('sf.shelf.location', string='当前货位', readonly=True)
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)
safe_inventory_id = fields.Many2one('sf.real.time.distribution.of.functional.tools',
string='功能刀具安全库存', readonly=True)
@api.depends('barcode_id.quant_ids', 'functional_tool_status', 'current_shelf_location_id')
@api.depends('barcode_id.quant_ids', 'functional_tool_status')
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
if record.functional_tool_status == '已拆除':
record.current_location_id = False
record.current_location = False
else:
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 == '制造前':
if not record.current_shelf_location_id:
record.current_location = '机内刀库'
else:
record.current_location = '线边刀库'
else:
record.current_location = '刀具房'
else:
record.current_location_id = False
record.current_location = False
record.tool_room_num = 0
record.line_edge_knife_library_num = 0
record.machine_knife_library_num = 0
@api.depends('current_location', 'functional_tool_status')
def _compute_num(self):
def get_location_num(self):
"""
计算库存位置数量
"""
for obj in self:
if obj.functional_tool_status == '已拆除':
if obj.current_location_id:
obj.tool_room_num = 0
obj.line_edge_knife_library_num = 0
obj.machine_knife_library_num = 0
else:
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
def tool_in_out_stock_location(self, location_id):
tool_room_id = self.env['stock.location'].search([('name', '=', '刀具房')])
pre_manufacturing_id = self.env['stock.location'].search([('name', '=', '制造前')])
for item in self:
# 中控反馈该位置有刀
if item:
# 系统该位置有刀
if location_id.product_sn_id:
# 中控反馈和系统中,该位置是同一把刀
if item.barcode_id == location_id.product_sn_id:
return True
# 中控反馈和系统中,该位置不是同一把刀
else:
# 原刀从线边出库
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
# 中控反馈该位置没有刀
else:
# 系统该位置有刀
if location_id.product_sn_id:
item.tool_in_out_stock_location_1(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(
[('barcode_id', '=', location_id.product_sn_id.id)])
if tool.current_location == '线边刀库':
tool.create_stock_move(tool_room_id, False)
# 修改功能刀具的当前位置
tool.current_shelf_location_id = False
def create_stock_move(self, location_dest_id, destination_location_id):
# 创建库存移动记录
stock_move_id = self.env['stock.move'].sudo().create({
'name': '/',
'product_id': self.barcode_id.product_id.id,
'location_id': self.current_location_id.id,
'location_dest_id': location_dest_id.id,
'product_uom_qty': 1.00,
'state': 'done'
})
# 创建移动历史记录
stock_move_line_id = self.env['stock.move.line'].sudo().create({
'product_id': self.barcode_id.product_id.id,
'lot_id': self.barcode_id.id,
'move_id': stock_move_id.id,
'current_location_id': False if not self.current_shelf_location_id else self.current_shelf_location_id.id,
'destination_location_id': False if not destination_location_id else destination_location_id.id,
'qty_done': 1.0,
'state': 'done',
'functional_tool_type_id': self.sf_cutting_tool_type_id.id,
'diameter': self.functional_tool_diameter,
'knife_tip_r_angle': self.knife_tip_r_angle,
'code': self.code,
'rfid': self.rfid,
'functional_tool_name': self.name,
'tool_groups_id': self.tool_groups_id.id
})
return stock_move_id, stock_move_line_id
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):
@@ -262,14 +192,12 @@ class FunctionalCuttingToolEntity(models.Model):
机床当前刀库实时信息接口,功能刀具出库
"""
# 获取位置对象
location_inventory_id = self.current_location_id
stock_location_id = self.env['stock.location'].search([('name', '=', '制造前')])
# 创建功能刀具该批次/序列号 库存移动和移动历史
self.create_stock_move(stock_location_id, False)
self.current_location_id = stock_location_id.id
self.current_shelf_location_id = False
# self.barcode_id.create_stock_quant(location_inventory_id, stock_location_id,
# self.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id,
# self.functional_tool_name_id.tool_groups_id)
self.barcode_id.create_stock_quant(location_inventory_id, stock_location_id,
self.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id,
self.functional_tool_name_id.tool_groups_id)
# ==========刀具组接口==========
# def _register_functional_tool_groups(self, obj):
@@ -377,7 +305,7 @@ class StockMoveLine(models.Model):
functional_tool_name = fields.Char('刀具名称')
diameter = fields.Float(string='刀具直径(mm)')
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
install_tool_time = fields.Datetime("刀具组装时间")
install_tool_time = fields.Datetime("刀具组装时间", default=fields.Datetime.now())
code = fields.Char('编码')
rfid = fields.Char('Rfid')
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组')
@@ -390,7 +318,6 @@ class StockMoveLine(models.Model):
class RealTimeDistributionOfFunctionalTools(models.Model):
_name = 'sf.real.time.distribution.of.functional.tools'
_inherit = ['mail.thread']
_description = '功能刀具安全库存'
name = fields.Char('名称', readonly=True, compute='_compute_name', store=True)
@@ -400,15 +327,15 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
group_expand='_read_mrs_cutting_tool_type_ids', store=True)
diameter = fields.Float(string='刀具直径(mm)', readonly=False)
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=False)
tool_stock_num = fields.Integer(string='刀具房数量', compute='_compute_stock_num', store=True)
side_shelf_num = fields.Integer(string='线边刀库数量', compute='_compute_stock_num', store=True)
on_tool_stock_num = fields.Integer(string='机内刀库数量', compute='_compute_stock_num', store=True)
tool_stock_total = fields.Integer(string='当前库存量', compute='_compute_tool_stock_total', store=True)
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',
store=True)
unit = fields.Char('单位', default="")
unit = fields.Char('单位')
image = fields.Binary('图片', readonly=False)
coarse_middle_thin = fields.Selection([("1", ""), ('2', ''), ('3', '')], string='粗/中/精', readonly=False)
@@ -476,6 +403,10 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
def _compute_batch_replenishment_num(self):
for tool in self:
if 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)
@@ -494,38 +425,6 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
else:
tool.sudo().batch_replenishment_num = 0
@api.depends('sf_functional_tool_entity_ids', 'sf_functional_tool_entity_ids.tool_room_num',
'sf_functional_tool_entity_ids.line_edge_knife_library_num',
'sf_functional_tool_entity_ids.machine_knife_library_num')
def _compute_stock_num(self):
"""
计算刀具房数量、线边刀库数量、机内刀库数量
"""
for tool in self:
if tool:
tool.tool_stock_num = 0
tool.side_shelf_num = 0
tool.on_tool_stock_num = 0
if tool.sf_functional_tool_entity_ids:
for cutting_tool in tool.sf_functional_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
else:
tool.tool_stock_num = 0
tool.side_shelf_num = 0
tool.on_tool_stock_num = 0
@api.depends('tool_stock_num', 'side_shelf_num', 'on_tool_stock_num')
def _compute_tool_stock_total(self):
for tool in self:
if tool:
# 计算当前库存量
tool.tool_stock_total = tool.tool_stock_num + tool.side_shelf_num + tool.on_tool_stock_num
def create_functional_tool_assembly(self, tool):
"""
创建功能刀具组装单
@@ -546,6 +445,27 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
})
tool.sudo().sf_functional_tool_assembly_ids = [(4, functional_tool_assembly.id)]
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_tool_entity_ids:
for cutting_tool in tool.sf_functional_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
else:
tool.tool_stock_num = 0
tool.side_shelf_num = 0
tool.on_tool_stock_num = 0
def create_or_edit_safety_stock(self, vals, sf_functional_tool_entity_ids):
"""
根据传入的信息新增或者更新功能刀具安全库存的信息

View File

@@ -80,7 +80,7 @@ class StockLot(models.Model):
headers = Common.get_headers(self, token, sf_secret_key)
str_url = sf_sync_config['sf_url'] + "/api/tool_material_stock/create"
product_ids = self.env['product.product'].sudo().search([('categ_type', '=', '刀具')]).ids
objs_all = self.env['stock.lot'].search([('product_id', 'in', product_ids)])
objs_all = self.env['stock.lot'].search([('rfid', '!=', False), ('product_id', 'in', product_ids)])
self._get_sync_stock_lot(objs_all, str_url, token, headers)
def _get_sync_stock_lot(self, objs_all, str_url, token, headers):
@@ -90,7 +90,6 @@ class StockLot(models.Model):
for item in objs_all:
val = {
'name': item.name,
'qty': item.product_qty,
'tool_material_status': item.tool_material_status,
'location': [] if not item.quant_ids else item.quant_ids[-1].location_id.name,
'tool_material_search_id': item.tool_material_search_id.id,
@@ -106,7 +105,7 @@ class StockLot(models.Model):
logging.info("没有刀具物料序列号信息")
except Exception as e:
logging.info("刀具物料序列号同步失败:%s" % e)
class ToolMaterial(models.Model):
_inherit = 'sf.tool.material.search'
@@ -164,6 +163,8 @@ class ToolMaterial(models.Model):
logging.info("刀具物料同步失败:%s" % e)
class FunctionalCuttingToolEntity(models.Model):
_inherit = 'sf.functional.cutting.tool.entity'
_description = '功能刀具列表注册'
@@ -234,7 +235,8 @@ class FunctionalCuttingToolEntity(models.Model):
'blade_tip_characteristics_name': item.blade_tip_characteristics_id.name,
'handle_type_name': item.handle_type_id.name,
'cutting_direction_names': get_cutting_direction_names(item),
'suitable_coolant_names': get_suitable_coolant_names(item)
'suitable_coolant_names': get_suitable_coolant_names(item),
'active': item.active,
}
functional_tool_list.append(val)
kw = json.dumps(functional_tool_list, ensure_ascii=False)
@@ -249,6 +251,8 @@ class FunctionalCuttingToolEntity(models.Model):
logging.info("功能刀具同步失败:%s" % e)
class FunctionalToolWarning(models.Model):
_inherit = 'sf.functional.tool.warning'
_description = '功能刀具预警注册'

View File

@@ -44,79 +44,71 @@ class SfMaintenanceEquipment(models.Model):
# ==========机床当前刀库实时信息接口==========
def register_equipment_tool(self):
try:
config = self.env['res.config.settings'].get_values()
# token = sf_sync_config['token'Ba F2CF5DCC-1A00-4234-9E95-65603F70CC8A]
headers = {'Authorization': config['center_control_Authorization']}
crea_url = config['center_control_url'] + "/AutoDeviceApi/GetToolInfos"
params = {"DeviceId": self.name}
r = requests.get(crea_url, params=params, headers=headers)
ret = r.json()
logging.info('register_equipment_tool:%s' % ret)
datas = ret['Datas']
self.write_maintenance_equipment_tool(datas)
if ret['Succeed']:
return "机床当前刀库实时信息指令发送成功"
else:
raise ValidationError("机床当前刀库实时信息指令发送失败")
except Exception as e:
logging.info("register_equipment_tool()捕获错误信息:%s" % e)
config = self.env['res.config.settings'].get_values()
# token = sf_sync_config['token'Ba F2CF5DCC-1A00-4234-9E95-65603F70CC8A]
headers = {'Authorization': config['center_control_Authorization']}
crea_url = config['center_control_url'] + "/AutoDeviceApi/GetToolInfos"
params = {"DeviceId": self.name}
r = requests.get(crea_url, params=params, headers=headers)
ret = r.json()
logging.info('register_equipment_tool:%s' % ret)
datas = ret['Datas']
self.write_maintenance_equipment_tool(datas)
if ret['Succeed']:
return "机床当前刀库实时信息指令发送成功"
else:
raise ValidationError("机床当前刀库实时信息指令发送失败")
def write_maintenance_equipment_tool(self, datas):
try:
if datas:
# 清除设备机床刀位的刀具信息
for obj in self.product_template_ids:
obj.write({
'functional_tool_name_id': False,
'tool_install_time': None
})
for data in datas:
maintenance_equipment_id = self.search([('name', '=', data['DeviceId'])])
if maintenance_equipment_id:
tool_id = '%s%s' % (data['ToolId'][0:1], data['ToolId'][1:].zfill(2))
equipment_tool_id = self.env['maintenance.equipment.tool'].sudo().search(
[('equipment_id', '=', maintenance_equipment_id.id), ('code', '=', tool_id)])
functional_tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search(
[('rfid', '=', data['RfidCode'])])
if functional_tool_id:
if len(functional_tool_id) > 1:
functional_tool_id = functional_tool_id[-1]
# 查询该功能刀具是否已经装在机床内其他位置,如果是就删除
equipment_tools = self.env['maintenance.equipment.tool'].sudo().search(
[('functional_tool_name_id', '=', functional_tool_id.id), ('code', '!=', tool_id)])
if equipment_tools:
for item in equipment_tools:
item.write({
'functional_tool_name_id': False,
'tool_install_time': None
})
else:
logging.info('Rfid为【%s】的功能刀具不存在!' % data['RfidCode'])
time = None
if data['AddDatetime']:
datatime = str(data['AddDatetime'])
time = fields.Datetime.from_string(datatime[0:10] + ' ' + datatime[11:19])
if equipment_tool_id and functional_tool_id:
tool_install_time = {'Nomal': '正常', 'Warning': '报警'}
equipment_tool_id.write({
'functional_tool_name_id': functional_tool_id.id,
'tool_install_time': time
})
if functional_tool_id.current_location != '机内刀库':
# 对功能刀具进行移动到生产线
functional_tool_id.tool_inventory_displacement_out()
functional_tool_id.write({
'max_lifetime_value': data['MaxLife'],
'used_value': data['UseLife'],
'functional_tool_status': tool_install_time.get(data['State'])
})
if datas:
# 清除设备机床刀位的刀具信息
for obj in self.product_template_ids:
obj.write({
'functional_tool_name_id': False,
'tool_install_time': None
})
for data in datas:
maintenance_equipment_id = self.search([('name', '=', data['DeviceId'])])
if maintenance_equipment_id:
tool_id = '%s%s' % (data['ToolId'][0:1], data['ToolId'][1:].zfill(2))
equipment_tool_id = self.env['maintenance.equipment.tool'].sudo().search(
[('equipment_id', '=', maintenance_equipment_id.id), ('code', '=', tool_id)])
functional_tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search(
[('rfid', '=', data['RfidCode'])])
if functional_tool_id:
# 查询该功能刀具是否已经装在机床内其他位置,如果是就删除
equipment_tools = self.env['maintenance.equipment.tool'].sudo().search(
[('functional_tool_name_id', '=', functional_tool_id.id), ('code', '!=', tool_id)])
if equipment_tools:
for item in equipment_tools:
item.write({
'functional_tool_name_id': False,
'tool_install_time': None
})
else:
logging.info('获取的%s设备不存在!' % data['DeviceId'])
else:
logging.info('没有获取到【%s】设备的刀具库信息!!!' % self.name)
except Exception as e:
logging.info("write_maintenance_equipment_tool()捕获错误信息:%s" % e)
logging.info('Rfid为%s的功能刀具不存在!' % data['RfidCode'])
time = None
if data['AddDatetime']:
datatime = str(data['AddDatetime'])
time = fields.Datetime.from_string(datatime[0:10] + ' ' + datatime[11:19])
if equipment_tool_id and functional_tool_id:
tool_install_time = {'Nomal': '正常', 'Warning': '报警'}
equipment_tool_id.write({
'functional_tool_name_id': functional_tool_id.id,
'tool_install_time': time
})
if functional_tool_id.current_location_id.name != '制造前':
# 对功能刀具进行出库到生产线
functional_tool_id.tool_inventory_displacement_out()
functional_tool_id.write({
'max_lifetime_value': data['MaxLife'],
'used_value': data['UseLife'],
'functional_tool_status': tool_install_time.get(data['State'])
})
else:
raise ValidationError('获取的【%s】设备不存在!!!' % data['DeviceId'])
else:
raise ValidationError('没有获取到刀具库信息!!!')
class StockLot(models.Model):

View File

@@ -1,23 +0,0 @@
from odoo import api, fields, models, _
class ShelfLocation(models.Model):
_inherit = 'sf.shelf.location'
tool_rfid = fields.Char('Rfid', compute='_compute_tool', store=True)
tool_name_id = fields.Many2one('sf.functional.cutting.tool.entity', string='功能刀具名称', compute='_compute_tool',
store=True)
@api.depends('product_id')
def _compute_tool(self):
for item in self:
if item.product_id:
if item.product_id.categ_id.name == '功能刀具':
tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search(
[('barcode_id', '=', item.product_sn_id.id)])
if tool_id:
item.tool_rfid = tool_id.rfid
item.tool_name_id = tool_id.id
continue
item.tool_rfid = ''
item.tool_name_id = False

View File

@@ -6,7 +6,7 @@
<field name="name">sf.functional.cutting.tool.entity.list.tree</field>
<field name="model">sf.functional.cutting.tool.entity</field>
<field name="arch" type="xml">
<tree string="功能刀具" create="0" edit="0" delete="0">
<tree string="功能刀具列表" create="0" edit="0" delete="0">
<field name="barcode_id" invisible="1"/>
<field name="rfid"/>
<field name="tool_name_id"/>
@@ -19,16 +19,15 @@
<field name="tool_loading_length" optional="hide"/>
<field name="functional_tool_length" optional="hide"/>
<field name="effective_length" optional="hide"/>
<field name="tool_room_num" optional="hide"/>
<field name="line_edge_knife_library_num" optional="hide"/>
<field name="machine_knife_library_num" optional="hide"/>
<field name="tool_room_num"/>
<field name="line_edge_knife_library_num"/>
<field name="machine_knife_library_num"/>
<field name="max_lifetime_value"/>
<field name="alarm_value"/>
<field name="used_value"/>
<field name="functional_tool_status"/>
<field name="current_location" string="当前位置"/>
<field name="current_location_id" invisible="1"/>
<field name="current_location_id" optional="hide"/>
<field name="current_location" optional="hide"/>
<field name="sf_cutting_tool_type_id" invisible="True"/>
</tree>
@@ -47,8 +46,8 @@
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<!-- <button name="button_safe_inventory_id" string="更新功能刀具关联的安全库存记录"-->
<!-- type="object" class="btn-primary"/>-->
<!-- <button name="button_safe_inventory_id" string="更新功能刀具关联的安全库存记录"-->
<!-- type="object" class="btn-primary"/>-->
<button class="oe_stat_button" groups="sf_base.group_sf_mrp_user"
name="open_functional_tool_warning"
icon="fa-list-ul"
@@ -87,7 +86,7 @@
</div>
<group>
<group>
<field name="barcode_id" invisible="0"/>
<field name="barcode_id" invisible="1"/>
<field name="rfid" readonly="1"
attrs="{'invisible': [('functional_tool_status', '=', '已拆除')]}"/>
<field name="rfid_dismantle" readonly="1"
@@ -116,7 +115,7 @@
options="{'no_create': True, 'no_quick_create': True}"/>
<field name="cutting_tool_cutterhead_model_id"
options="{'no_create': True, 'no_quick_create': True}"/>
<field name="safe_inventory_id" invisible="1"/>
<field name="safe_inventory_id" readonly="0"/>
</group>
<group>
<field name="image" nolabel="1" widget="image"/>
@@ -174,10 +173,7 @@
<field name="cut_time" attrs="{'invisible': [('new_former','=','0')]}"/>
<field name="cut_length" attrs="{'invisible': [('new_former','=','0')]}"/>
<field name="cut_number" attrs="{'invisible': [('new_former','=','0')]}"/>
<field name="current_location_id" string="当前位置"/>
<field name="current_location" string="当前位置"/>
<field name="current_shelf_location_id" string="当前货位"
attrs="{'invisible': [('current_shelf_location_id', '=', False)]}"/>
</group>
</group>
</page>
@@ -193,34 +189,19 @@
<field name="arch" type="xml">
<search>
<field name="rfid"/>
<field name="barcode_id"/>
<field name="tool_name_id"/>
<field name="functional_tool_diameter"/>
<field name="knife_tip_r_angle"/>
<filter string="刀具房" name="tool_room" domain="[('current_location', '=', '刀具房')]"/>
<filter string="线边刀库" name="storage_area" domain="[('current_location', '=', '线边刀库')]"/>
<filter string="机内刀库" name="machine_knife_library"
domain="[('current_location', '=', '机内刀库')]"/>
<separator/>
<filter string="正常" name="normal" domain="[('functional_tool_status', '=', '正常')]"/>
<filter string="报警" name="alarm" domain="[('functional_tool_status', '=', '报警')]"/>
<separator/>
<filter string="未拆除" name="no_state_removed"
domain="[('functional_tool_status', '!=', '已拆除')]"/>
<filter string="已拆除" name="state_removed" domain="[('functional_tool_status', '=', '已拆除')]"/>
<separator/>
<filter string="已归档" name="inactive" domain="[('active', '=', False)]"/>
<searchpanel>
<field name="sf_cutting_tool_type_id" icon="fa-building" enable_counters="1"/>
<field name="current_location" icon="fa-building" enable_counters="1"/>
<field name="functional_tool_status" icon="fa-building" enable_counters="1"/>
<field name="sf_cutting_tool_type_id" icon="fa-building" enable_counters="1"/>
</searchpanel>
<group expand="0">
<filter string="功能刀具名称" name="tool_name" domain="[]"
context="{'group_by': 'tool_name_id'}"/>
<filter string="刀具组" name="tool_groups" domain="[]"
context="{'group_by': 'tool_groups_id'}"/>
<filter string="当前位置" name="current_location" domain="[]"
context="{'group_by': 'current_location'}"/>
</group>
</search>
</field>
</record>
@@ -316,10 +297,11 @@
<tree>
<field name="name" invisible="1"/>
<field name="functional_name_id"/>
<field name="sf_cutting_tool_type_id" invisible="True"/>
<field name="tool_groups_id"/>
<field name="diameter"/>
<field name="knife_tip_r_angle"/>
<field name="coarse_middle_thin" optional="hide"/>
<field name="coarse_middle_thin"/>
<field name="tool_stock_num"/>
<field name="side_shelf_num"/>
<field name="on_tool_stock_num"/>
@@ -328,8 +310,6 @@
<field name="max_stock_num"/>
<field name="batch_replenishment_num"/>
<field name="unit"/>
<field name="sf_cutting_tool_type_id" invisible="True"/>
</tree>
</field>
</record>
@@ -431,10 +411,6 @@
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="message_ids"/>
</div>
</form>
</field>
</record>
@@ -445,20 +421,21 @@
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="tool_groups_id"/>
<field name="sf_cutting_tool_type_id"/>
<field name="sf_cutting_tool_type_id" invisible="True"/>
<field name="diameter"/>
<field name="knife_tip_r_angle"/>
<filter string="需补货" name="batch_replenishment" domain="[('batch_replenishment_num', '>', 0)]"/>
<separator/>
<field name="tool_stock_num"/>
<field name="side_shelf_num"/>
<field name="on_tool_stock_num"/>
<field name="tool_stock_total"/>
<field name="min_stock_num"/>
<field name="max_stock_num"/>
<field name="batch_replenishment_num"/>
<field name="unit"/>
<filter string="已归档" name="inactive" domain="[('active', '=', False)]"/>
<searchpanel>
<field name="sf_cutting_tool_type_id" enable_counters="1" icon="fa-building"/>
</searchpanel>
<group expand="0">
<filter string="刀具组" name="tool_groups" domain="[]"
context="{'group_by': 'tool_groups_id'}"/>
</group>
</search>
</field>
</record>
@@ -487,9 +464,7 @@
<field name="knife_tip_r_angle"/>
<field name="install_tool_time"/>
<field name="location_id"/>
<field name="current_location_id"/>
<field name="location_dest_id"/>
<field name="destination_location_id"/>
<field name="date"/>
<field name="qty_done" string="数量"/>
<field name="functional_tool_type_id" invisible="True"/>
@@ -504,20 +479,21 @@
<field name="model">stock.move.line</field>
<field name="arch" type="xml">
<search>
<field name="reference"/>
<field name="lot_id"/>
<field name="rfid"/>
<field name="functional_tool_name"/>
<field name="diameter"/>
<field name="knife_tip_r_angle"/>
<field name="reference"/>
<field name="lot_id"/>
<field name="install_tool_time"/>
<field name="location_id"/>
<field name="location_dest_id"/>
<field name="date"/>
<field name="qty_done"/>
<field name="functional_tool_type_id" invisible="True"/>
<searchpanel>
<field name="functional_tool_type_id" enable_counters="1" icon="fa-building"/>
</searchpanel>
<group expand="0">
<filter string="功能刀具名称" name="functional_tool_name" domain="[]"
context="{'group_by': 'functional_tool_name'}"/>
<filter string="日期" name="date" domain="[]" context="{'group_by': 'date'}"/>
</group>
</search>
</field>
</record>
@@ -531,7 +507,7 @@
ref="sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_tree"/>
<field name="search_view_id"
ref="sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_search"/>
<field name="domain">[('functional_tool_name', '!=', False)]</field>
<field name="domain">[('functional_tool_name_id', '!=', False)]</field>
</record>
</data>

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_shelf_location_tool" model="ir.ui.view">
<field name="name">sf.shelf.location.form.tool</field>
<field name="model">sf.shelf.location</field>
<field name="inherit_id" ref="sf_warehouse.view_shelf_location_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='product_id']" position="after">
<field name="tool_rfid" attrs="{'invisible': [('tool_name_id', '=', False)]}"/>
<field name="tool_name_id" attrs="{'invisible': [('tool_name_id', '=', False)]}"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -376,10 +376,6 @@
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="message_ids"/>
</div>
</form>
</field>
</record>
@@ -434,17 +430,17 @@
<field name="code" optional="hide"/>
<field name="functional_tool_name"/>
<field name="tool_groups_id"/>
<field name="functional_tool_diameter" string="刀具直径(mm)"/>
<field name="functional_tool_diameter" string="刀具直径"/>
<field name="knife_tip_r_angle"/>
<field name="coarse_middle_thin" optional="hide"/>
<field name="new_former" optional="hide"/>
<field name="tool_loading_length" optional="hide"/>
<field name="functional_tool_length" optional="hide"/>
<field name="effective_length" invisible="1"/>
<field name="effective_length" optional="hide"/>
<field name="loading_task_source" string="任务来源"/>
<field name="use_tool_time"/>
<field name="production_line_name_id" optional="hide"/>
<field name="machine_tool_name_id" optional="hide"/>
<field name="production_line_name_id"/>
<field name="machine_tool_name_id"/>
<field name="applicant"/>
<field name="apply_time"/>
<field name="assemble_status" optional="hide"/>
@@ -468,8 +464,8 @@
<field name="arch" type="xml">
<form create="0" delete="0" edit="0">
<header>
<!-- <button string="修改编码" name="put_assembly_order_code" type="object"-->
<!-- class="btn-primary" confirm="是否确认修改编码"/>-->
<!-- <button string="修改编码" name="put_assembly_order_code" type="object"-->
<!-- class="btn-primary" confirm="是否确认修改编码"/>-->
<button string="组装" name="put_start_preset" type="object"
attrs="{'invisible': [('assemble_status', '!=', '0')]}"
class="btn-primary"/>
@@ -532,10 +528,8 @@
<field name="after_assembly_max_lifetime_value"
string="最大寿命值(min)"/>
<field name="after_assembly_alarm_value" string="报警值(min)"/>
<field name="after_assembly_used_value" string="已使用值(min)"
invisible="1"/>
<field name="after_assembly_effective_length" string="有效长(mm)"
invisible="1"/>
<field name="after_assembly_used_value" string="已使用值(min)" invisible="1"/>
<field name="after_assembly_effective_length" string="有效长(mm)" invisible="1"/>
<field name="L_D_number" invisible="1"/>
<field name="hiding_length" invisible="1"/>
</group>
@@ -557,14 +551,13 @@
<field name="sf_tool_brand_id_5" string="品牌"/>
</group>
</group>
<group col="1" attrs="{'invisible': [('chuck_freight_barcode_id', '=', False)]}">
<group col="1" attrs="{'invisible': [('chuck_freight_barcode', '=', False)]}">
<div>
<separator string="夹头:" style="font-size: 13px;"/>
</div>
<group>
<group>
<field name="chuck_freight_barcode_id" string="货位"/>
<field name="chuck_lot_id" string="批次"/>
<field name="chuck_freight_barcode" string="货位"/>
<field name="chuck_product_id" string="名称"/>
<field name="cutting_tool_cutterhead_model_id" string="型号"/>
<field name="chuck_specification_id" string="规格"/>
@@ -576,27 +569,24 @@
<group>
<group col="1">
<group col="1"
attrs="{'invisible': [('integral_freight_barcode_id', '=', False)]}">
attrs="{'invisible': [('integral_freight_barcode', '=', False)]}">
<div>
<separator string="整体式刀具:" style="font-size: 13px;"/>
</div>
<group>
<field name="integral_freight_barcode_id" string="货位"/>
<field name="integral_lot_id" string="批次"/>
<field name="integral_freight_barcode" string="货位"/>
<field name="integral_product_id" string="名称"/>
<field name="cutting_tool_integral_model_id" string="型号"/>
<field name="integral_specification_id" string="规格"/>
<field name="sf_tool_brand_id_1" string="品牌"/>
</group>
</group>
<group col="1"
attrs="{'invisible': [('blade_freight_barcode_id', '=', False)]}">
<group col="1" attrs="{'invisible': [('blade_freight_barcode', '=', False)]}">
<div>
<separator string="刀片:" style="font-size: 13px;"/>
</div>
<group>
<field name="blade_freight_barcode_id" string="货位"/>
<field name="blade_lot_id" string="批次"/>
<field name="blade_freight_barcode" string="货位"/>
<field name="blade_product_id" string="名称"/>
<field name="cutting_tool_blade_model_id" string="型号"/>
<field name="blade_specification_id" string="规格"/>
@@ -605,14 +595,13 @@
</group>
</group>
<group col="1">
<group col="1" attrs="{'invisible': [('bar_freight_barcode_id', '=', False)]}">
<group col="1" attrs="{'invisible': [('bar_freight_barcode', '=', False)]}">
<div>
<separator string="刀杆:" style="font-size: 13px;"/>
</div>
<group>
<group>
<field name="bar_freight_barcode_id" string="货位"/>
<field name="bar_lot_id" string="批次"/>
<field name="bar_freight_barcode" string="货位"/>
<field name="bar_product_id" string="名称"/>
<field name="cutting_tool_cutterbar_model_id" string="型号"/>
<field name="bar_specification_id" string="规格"/>
@@ -620,14 +609,13 @@
</group>
</group>
</group>
<group col="1" attrs="{'invisible': [('pad_freight_barcode_id', '=', False)]}">
<group col="1" attrs="{'invisible': [('pad_freight_barcode', '=', False)]}">
<div>
<separator string="刀盘:" style="font-size: 13px;"/>
</div>
<group>
<group>
<field name="pad_freight_barcode_id" string="货位"/>
<field name="pad_lot_id" string="批次"/>
<field name="pad_freight_barcode" string="货位"/>
<field name="pad_product_id" string="名称"/>
<field name="cutting_tool_cutterpad_model_id" string="型号"/>
<field name="pad_specification_id" string="规格"/>
@@ -680,10 +668,6 @@
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="message_ids"/>
</div>
</form>
</field>
</record>
@@ -693,29 +677,30 @@
<field name="arch" type="xml">
<search>
<field name="assembly_order_code"/>
<field name="code" string="功能刀具编码"/>
<field name="barcode_id"/>
<field name="barcode_id" optional="hide"/>
<field name="functional_tool_name"/>
<field name="functional_tool_type_id"/>
<field name="tool_groups_id"/>
<field name="functional_tool_diameter"/>
<field name="knife_tip_r_angle"/>
<field name="coarse_middle_thin"/>
<field name="new_former"/>
<field name="tool_loading_length"/>
<field name="functional_tool_length"/>
<field name="effective_length"/>
<field name="loading_task_source" string="任务来源"/>
<field name="use_tool_time"/>
<field name="production_line_name_id"/>
<field name="machine_tool_name_id"/>
<field name="applicant"/>
<field name="apply_time"/>
<field name="functional_tool_type_id"/>
<filter name="no_assemble_status" string="未组装" domain="[('assemble_status', '=', '0')]"/>
<filter name="yes_assemble_status" string="已组装" domain="[('assemble_status', '=', '1')]"/>
<separator/>
<filter string="已归档" name="inactive" domain="[('active', '=', False)]"/>
<searchpanel>
<field name="functional_tool_type_id" enable_counters="1" icon="fa-filter"/>
<!-- <field name="assemble_status" enable_counters="1" icon="fa-filter"/>-->
</searchpanel>
<group expand="0" string="Group By...">
<filter string="功能刀具名称" name="name" domain="[]" context="{'group_by': 'functional_tool_name'}"/>
<filter string="刀具组" name="tool_groups" domain="[]" context="{'group_by': 'tool_groups_id'}"/>
<filter string="任务来源" name="loading_task_source" domain="[]" context="{'group_by': 'loading_task_source'}"/>
<filter string="用刀时间" name="use_tool_time" domain="[]" context="{'group_by': 'use_tool_time'}"/>
</group>
</search>
</field>
</record>
@@ -737,7 +722,6 @@
<field name="model">sf.functional.tool.dismantle</field>
<field name="arch" type="xml">
<tree create="1">
<field name="code"/>
<field name="rfid"/>
<field name="functional_tool_id"/>
<field name="tool_type_id" invisible="1"/>
@@ -765,14 +749,13 @@
<sheet>
<div class="oe_title">
<h1>
<field name="code"/>
<field name="functional_tool_id" placeholder="请选择将要拆解的功能刀具"
options="{'no_create': True}" attrs="{'readonly': [('state', '=', '已拆解')]}"/>
</h1>
</div>
<field name="_barcode_scanned" widget="barcode_handler"/>
<group>
<group>
<field name="functional_tool_id" placeholder="请选择将要拆解的功能刀具"
options="{'no_create': True}" attrs="{'readonly': [('state', '=', '已拆解')]}"/>
<field name="rfid" attrs="{'invisible': [('state', '=', '已拆解')]}"/>
<field name="rfid_dismantle" attrs="{'invisible': [('state', '!=', '已拆解')]}"/>
<field name="tool_type_id"/>
@@ -803,98 +786,91 @@
<group>
<group string="刀柄" attrs="{'invisible': [('handle_product_id', '=', False)]}">
<group>
<field name="scrap_boolean" string="是否报废"
attrs="{'invisible': [('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])], 'readonly': [('state', '=', '已拆解')]}"/>
<field name="handle_rfid" string="Rfid"/>
<field name="handle_lot_id" string="序列号"/>
<field name="handle_product_id" string="名称"/>
<field name="handle_type_id" string="型号"/>
<field name="handle_brand_id" string="品牌"/>
</group>
<group>
<field name="handle_rfid" string="Rfid"/>
<field name="scrap_boolean" string="是否报废"
attrs="{'invisible': [('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])], 'readonly': [('state', '=', '已拆解')]}"/>
</group>
</group>
<group string="夹头"
attrs="{'invisible': [('chuck_product_id', '=', False)]}">
<group>
<field name="chuck_freight_id" string="目标货位" placeholder="请选择"
options="{'no_create': True,'no_create_edit':True}"
attrs="{'invisible': [('dismantle_cause', 'not in', ['更换为其他刀具', '刀具需磨削'])], 'readonly': [('state', '=', '已拆解')],
'required': [('chuck_lot_id', '!=', False),('dismantle_cause', 'in', ['更换为其他刀具', '刀具需磨削'])]}"/>
<field name="chuck_lot_id" string="批次"/>
<field name="chuck_product_id" string="名称"/>
<field name="chuck_type_id" string="型号"/>
<field name="chuck_brand_id" string="品牌"/>
</group>
<group>
<field name="chuck_freight_id" string="目标货位"
options="{'no_create': True,'no_create_edit':True}"
attrs="{'invisible': [('dismantle_cause', 'not in', ['更换为其他刀具'])], 'readonly': [('state', '=', '已拆解')],
'required': [('chuck_product_id', '!=', False),('dismantle_cause', 'in', ['更换为其他刀具'])]}"/>
</group>
</group>
</group>
<group attrs="{'invisible': [('integral_product_id', '=', False)]}">
<group string="整体式刀具">
<group>
<field name="integral_freight_id" string="目标货位" placeholder="请选择"
options="{'no_create': True,'no_create_edit':True}"
attrs="{'invisible': [('dismantle_cause', 'not in', ['更换为其他刀具', '刀具需磨削'])], 'readonly': [('state', '=', '已拆解')],
'required': [('integral_lot_id', '!=', False),('dismantle_cause', 'in', ['更换为其他刀具', '刀具需磨削'])]}"/>
<field name="integral_lot_id" string="批次"/>
<field name="integral_product_id" string="名称"/>
<field name="integral_type_id" string="型号"/>
<field name="integral_brand_id" string="品牌"/>
</group>
<group>
<field name="integral_freight_id" string="目标货位"
options="{'no_create': True,'no_create_edit':True}"
attrs="{'invisible': [('dismantle_cause', 'not in', ['更换为其他刀具'])], 'readonly': [('state', '=', '已拆解')],
'required': [('integral_product_id', '!=', False),('dismantle_cause', 'in', ['更换为其他刀具'])]}"/>
</group>
</group>
</group>
<group>
<group string="刀片" attrs="{'invisible': [('blade_product_id', '=', False)]}">
<group>
<field name="blade_freight_id" string="目标货位" placeholder="请选择"
options="{'no_create': True,'no_create_edit':True}"
attrs="{'invisible': [('dismantle_cause', 'not in', ['更换为其他刀具', '刀具需磨削'])], 'readonly': [('state', '=', '已拆解')],
'required': [('blade_lot_id', '!=', False),('dismantle_cause', 'in', ['更换为其他刀具', '刀具需磨削'])]}"/>
<field name="blade_lot_id" string="批次"/>
<field name="blade_product_id" string="名称"/>
<field name="blade_type_id" string="型号"/>
<field name="blade_brand_id" string="品牌"/>
</group>
<group>
<field name="blade_freight_id" string="目标货位"
options="{'no_create': True,'no_create_edit':True}"
attrs="{'invisible': [('dismantle_cause', 'not in', ['更换为其他刀具'])], 'readonly': [('state', '=', '已拆解')],
'required': [('blade_product_id', '!=', False),('dismantle_cause', 'in', ['更换为其他刀具'])]}"/>
</group>
</group>
<group string="刀杆" attrs="{'invisible': [('bar_product_id', '=', False)]}">
<group>
<field name="bar_freight_id" string="目标货位" placeholder="请选择"
options="{'no_create': True,'no_create_edit':True}"
attrs="{'invisible': [('dismantle_cause', 'not in', ['更换为其他刀具', '刀具需磨削'])], 'readonly': [('state', '=', '已拆解')],
'required': [('bar_lot_id', '!=', False),('dismantle_cause', 'in', ['更换为其他刀具', '刀具需磨削'])]}"/>
<field name="bar_lot_id" string="批次"/>
<field name="bar_product_id" string="名称"/>
<field name="bar_type_id" string="型号"/>
<field name="bar_brand_id" string="品牌"/>
</group>
<group>
<field name="bar_freight_id" string="目标货位"
options="{'no_create': True,'no_create_edit':True}"
attrs="{'invisible': [('dismantle_cause', 'not in', ['更换为其他刀具'])], 'readonly': [('state', '=', '已拆解')],
'required': [('bar_product_id', '!=', False),('dismantle_cause', 'in', ['更换为其他刀具'])]}"/>
</group>
</group>
<group string="刀盘" attrs="{'invisible': [('pad_product_id', '=', False)]}">
<group>
<field name="pad_freight_id" string="目标货位" placeholder="请选择"
options="{'no_create': True,'no_create_edit':True}"
attrs="{'invisible': [('dismantle_cause', 'not in', ['更换为其他刀具', '刀具需磨削'])], 'readonly': [('state', '=', '已拆解')],
'required': [('pad_lot_id', '!=', False), ('dismantle_cause', 'in', ['更换为其他刀具', '刀具需磨削'])]}"/>
<field name="pad_lot_id" string="批次"/>
<field name="pad_product_id" string="名称"/>
<field name="pad_type_id" string="型号"/>
<field name="pad_brand_id" string="品牌"/>
</group>
</group>
</group>
</page>
<page string="其他">
<group>
<group>
<field name="dismantle_person"/>
</group>
<group>
<field name="dismantle_data"/>
<group>
<field name="pad_freight_id" string="目标货位"
options="{'no_create': True,'no_create_edit':True}"
attrs="{'invisible': [('dismantle_cause', 'not in', ['更换为其他刀具'])], 'readonly': [('state', '=', '已拆解')],
'required': [('pad_product_id', '!=', False), ('dismantle_cause', 'in', ['更换为其他刀具'])]}"/>
</group>
</group>
</group>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="message_ids"/>
</div>
</form>
</field>
</record>
@@ -904,7 +880,6 @@
<field name="arch" type="xml">
<search>
<field name="functional_tool_id"/>
<field name="code" string="拆解单编码"/>
<filter name="no_dismantle_state" string="未拆解" domain="[('state','!=','已拆解')]"/>
<filter name="dismantle_state" string="已拆解" domain="[('state','=','已拆解')]"/>
<separator/>

View File

@@ -62,7 +62,6 @@
<tree>
<field name="name"/>
<field name="rfid"/>
<field name="product_qty"/>
<field name="tool_material_status"/>
<!-- <button name="enroll_tool_material_stock" string="序列号注册" type="object" class="btn-primary"/>-->
</tree>

View File

@@ -233,10 +233,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 功能刀具组装信息
# ===============整体式刀具型号=================
integral_freight_barcode_id = fields.Many2one('sf.shelf.location', string='整体式刀具货位',
domain="[('product_id.cutting_tool_material_id.name', '=', '整体式刀具'),('product_num', '>', 0)]")
integral_freight_lot_id = fields.Many2one('sf.shelf.location.lot', string='整体式刀具批次',
domain="[('shelf_location_id', '=', integral_freight_barcode_id)]")
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='整体式刀具型号',
@@ -246,23 +243,28 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
sf_tool_brand_id_1 = fields.Many2one('sf.machine.brand', string='整体式刀具品牌',
related='integral_product_id.brand_id')
@api.onchange('integral_freight_barcode_id')
def _onchange_integral_freight_barcode_id(self):
for item in self:
item.integral_freight_lot_id = False
@api.depends('integral_freight_lot_id')
@api.depends('integral_freight_barcode')
def _compute_integral_product_id(self):
if self.integral_freight_lot_id:
self.integral_product_id = self.integral_freight_lot_id.lot_id.product_id.id
else:
self.integral_product_id = False
if self.integral_freight_barcode:
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.integral_freight_barcode)])
if location:
if not location.product_id:
raise ValidationError('编码为【%s】的货位为空货位!' % location.barcode)
else:
material_name_id = location.product_id.cutting_tool_material_id
if material_name_id and material_name_id.name == '整体式刀具':
if location.product_num == 0:
raise ValidationError('编码为【%s】的货位的产品库存数量为0,请重新选择!' % location.barcode)
self.integral_product_id = location.product_id.id
else:
raise ValidationError(
'编码为【%s】的货位存放的产品为【%s】,不是整体式刀具,请重新选择!' % (
location.barcode, location.product_id.name))
else:
raise ValidationError('编码为【%s】的货位不存在!' % self.integral_freight_barcode)
# ===============刀片型号====================
blade_freight_barcode_id = fields.Many2one('sf.shelf.location', string='刀片货位',
domain="[('product_id.cutting_tool_material_id.name', '=', '刀片'),('product_num', '>', 0)]")
blade_freight_lot_id = fields.Many2one('sf.shelf.location.lot', string='刀片批次',
domain="[('shelf_location_id', '=', blade_freight_barcode_id)]")
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='刀片型号',
@@ -271,23 +273,28 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
related='blade_product_id.specification_id')
sf_tool_brand_id_2 = fields.Many2one('sf.machine.brand', '刀片品牌', related='blade_product_id.brand_id')
@api.onchange('blade_freight_barcode_id')
def _onchange_blade_freight_barcode_id(self):
for item in self:
item.blade_freight_lot_id = False
@api.depends('blade_freight_lot_id')
@api.depends('blade_freight_barcode')
def _compute_blade_product_id(self):
if self.blade_freight_lot_id:
self.blade_product_id = self.blade_freight_lot_id.lot_id.product_id.id
else:
self.blade_product_id = False
if self.blade_freight_barcode:
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.blade_freight_barcode)])
if location:
if not location.product_id:
raise ValidationError('编码为【%s】的货位为空货位!' % location.barcode)
else:
material_name_id = location.product_id.cutting_tool_material_id
if material_name_id and material_name_id.name == '刀片':
if location.product_num == 0:
raise ValidationError('编码为【%s】的货位的产品库存数量为0,请重新选择!' % location.barcode)
self.blade_product_id = location.product_id.id
else:
raise ValidationError(
'编码为【%s】的货位存放的产品为【%s】,不是刀片,请重新选择!' % (
location.barcode, location.product_id.name))
else:
raise ValidationError('编码为【%s】的货位不存在!' % self.blade_freight_barcode)
# ====================刀杆型号==================
bar_freight_barcode_id = fields.Many2one('sf.shelf.location', string='刀杆货位',
domain="[('product_id.cutting_tool_material_id.name', '=', '刀杆'),('product_num', '>', 0)]")
bar_freight_lot_id = fields.Many2one('sf.shelf.location.lot', string='刀杆批次',
domain="[('shelf_location_id', '=', bar_freight_barcode_id)]")
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='刀杆型号',
@@ -296,23 +303,28 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
related='bar_product_id.specification_id')
sf_tool_brand_id_3 = fields.Many2one('sf.machine.brand', '刀杆品牌', related='bar_product_id.brand_id')
@api.onchange('bar_freight_barcode_id')
def _onchange_bar_freight_barcode_id(self):
for item in self:
item.bar_freight_lot_id = False
@api.depends('bar_freight_lot_id')
@api.depends('bar_freight_barcode')
def _compute_bar_product_id(self):
if self.bar_freight_lot_id:
self.bar_product_id = self.bar_freight_lot_id.lot_id.product_id.id
else:
self.bar_product_id = False
if self.bar_freight_barcode:
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.bar_freight_barcode)])
if location:
if not location.product_id:
raise ValidationError('编码为【%s】的货位为空货位!' % location.barcode)
else:
material_name_id = location.product_id.cutting_tool_material_id
if material_name_id and material_name_id.name == '刀杆':
if location.product_num == 0:
raise ValidationError('编码为【%s】的货位的产品库存数量为0,请重新选择!' % location.barcode)
self.bar_product_id = location.product_id.id
else:
raise ValidationError(
'编码为【%s】的货位存放的产品为【%s】,不是刀杆,请重新选择!' % (
location.barcode, location.product_id.name))
else:
raise ValidationError('编码为【%s】的货位不存在!' % self.bar_freight_barcode)
# ===============刀盘型号===================
pad_freight_barcode_id = fields.Many2one('sf.shelf.location', string='刀盘货位',
domain="[('product_id.cutting_tool_material_id.name', '=', '刀盘'),('product_num', '>', 0)]")
pad_freight_lot_id = fields.Many2one('sf.shelf.location.lot', string='刀盘批次',
domain="[('shelf_location_id', '=', pad_freight_barcode_id)]")
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='刀盘型号',
@@ -321,17 +333,25 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
related='pad_product_id.specification_id')
sf_tool_brand_id_4 = fields.Many2one('sf.machine.brand', '刀盘品牌', related='pad_product_id.brand_id')
@api.onchange('pad_freight_barcode_id')
def _onchange_pad_freight_barcode_id(self):
for item in self:
item.pad_freight_lot_id = False
@api.depends('pad_freight_lot_id')
@api.depends('pad_freight_barcode')
def _compute_pad_product_id(self):
if self.pad_freight_lot_id:
self.pad_product_id = self.pad_freight_lot_id.lot_id.product_id.id
else:
self.pad_product_id = False
if self.pad_freight_barcode:
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.pad_freight_barcode)])
if location:
if not location.product_id:
raise ValidationError('编码为【%s】的货位为空货位!' % location.barcode)
else:
material_name_id = location.product_id.cutting_tool_material_id
if material_name_id and material_name_id.name == '刀盘':
if location.product_num == 0:
raise ValidationError('编码为【%s】的货位的产品库存数量为0,请重新选择!' % location.barcode)
self.pad_product_id = location.product_id.id
else:
raise ValidationError(
'编码为【%s】的货位存放的产品为【%s】,不是刀盘,请重新选择!' % (
location.barcode, location.product_id.name))
else:
raise ValidationError('编码为【%s】的货位不存在!' % self.pad_freight_barcode)
# ================刀柄型号===============
handle_freight_rfid = fields.Char('刀柄Rfid', compute='_compute_rfid')
@@ -354,10 +374,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
self.pad_product_id = False
# =================夹头型号==============
chuck_freight_barcode_id = fields.Many2one('sf.shelf.location', string='夹头货位',
domain="[('product_id.cutting_tool_material_id.name', '=', '夹头'),('product_num', '>', 0)]")
chuck_freight_lot_id = fields.Many2one('sf.shelf.location.lot', string='夹头批次',
domain="[('shelf_location_id', '=', chuck_freight_barcode_id)]")
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='夹头型号',
@@ -366,17 +383,25 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
related='chuck_product_id.specification_id')
sf_tool_brand_id_6 = fields.Many2one('sf.machine.brand', '夹头品牌', related='chuck_product_id.brand_id')
@api.onchange('chuck_freight_barcode_id')
def _onchange_chuck_freight_barcode_id(self):
for item in self:
item.chuck_freight_lot_id = False
@api.depends('chuck_freight_lot_id')
@api.depends('chuck_freight_barcode')
def _compute_chuck_product_id(self):
if self.chuck_freight_lot_id:
self.chuck_product_id = self.chuck_freight_lot_id.lot_id.product_id.id
else:
self.chuck_product_id = False
if self.chuck_freight_barcode:
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.chuck_freight_barcode)])
if location:
if not location.product_id:
raise ValidationError('编码为【%s】的货位为空货位!' % location.barcode)
else:
material_name_id = location.product_id.cutting_tool_material_id
if material_name_id and material_name_id.name == '夹头':
if location.product_num == 0:
raise ValidationError('编码为【%s】的货位的产品库存数量为0,请重新选择!' % location.barcode)
self.chuck_product_id = location.product_id.id
else:
raise ValidationError(
'编码为【%s】的货位存放的产品为【%s】,不是夹头,请重新选择!' % (
location.barcode, location.product_id.name))
else:
raise ValidationError('编码为【%s】的货位不存在!' % self.chuck_freight_barcode)
# ========================================
def on_barcode_scanned(self, barcode):
@@ -398,23 +423,23 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
if location:
material_name = location.product_id.cutting_tool_material_id.name
if material_name == '夹头':
record.chuck_freight_barcode_id = location.id
record.chuck_freight_barcode = barcode
elif material_name == '整体式刀具':
record.integral_freight_barcode_id = location.id
record.blade_freight_barcode_id = False
record.bar_freight_barcode_id = False
record.pad_freight_barcode_id = False
record.integral_freight_barcode = barcode
record.blade_freight_barcode = ''
record.bar_freight_barcode = ''
record.pad_freight_barcode = ''
elif material_name == '刀片':
record.blade_freight_barcode_id = location.id
record.integral_freight_barcode_id = False
record.blade_freight_barcode = barcode
record.integral_freight_barcode = ''
elif material_name == '刀杆':
record.bar_freight_barcode_id = location.id
record.integral_freight_barcode_id = False
record.pad_freight_barcode_id = False
record.bar_freight_barcode = barcode
record.integral_freight_barcode = ''
record.pad_freight_barcode = ''
elif material_name == '刀盘':
record.pad_freight_barcode_id = location.id
record.integral_freight_barcode_id = False
record.bar_freight_barcode_id = False
record.pad_freight_barcode = barcode
record.integral_freight_barcode = ''
record.bar_freight_barcode = ''
else:
raise ValidationError('扫描的刀具物料不存在,请重新扫描!')
else:
@@ -465,15 +490,6 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
compute='_compute_after_assembly_max_lifetime_value')
obtain_measurement_status = fields.Boolean('是否获取测量值', default=False)
enable_tool_presetter = fields.Boolean('是否启用刀具预调仪', default=lambda self: self.get_enable_tool_presetter())
def get_enable_tool_presetter(self):
"""
获取是否启用刀具预调仪数据
"""
sf_sync_config = self.env['res.config.settings'].get_values()
enable_tool_presetter = sf_sync_config['enable_tool_presetter']
return enable_tool_presetter
@api.depends('after_assembly_tool_loading_length', 'after_assembly_handle_length')
def _compute_after_assembly_functional_tool_length(self):
@@ -537,21 +553,32 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# functional_tool_cutting_type = fields.Char(string='功能刀具切削类型', readonly=False)
# res_partner_id = fields.Many2one('res.partner', '智能工厂', domain="[('is_factory', '=', True)]")
@api.depends('after_assembly_functional_tool_type_id', 'cutting_tool_cutterhandle_model_id',
'after_assembly_functional_tool_diameter', 'after_assembly_tool_loading_length',
'after_assembly_knife_tip_r_angle', 'after_assembly_functional_tool_length',
'after_assembly_handle_length')
@api.depends('after_assembly_functional_tool_type_id', 'integral_specification_id', 'bar_specification_id',
'pad_specification_id', 'handle_specification_id', 'after_assembly_tool_loading_length')
def _compute_code(self):
for obj in self:
if obj.cutting_tool_cutterhandle_model_id:
code = obj.cutting_tool_cutterhandle_model_id.code.split('-', 1)[0]
str_1 = '%s-GNDJ-%s-D%sL%sR%sB%sH%s' % (
code, obj.after_assembly_functional_tool_type_id.code, obj.after_assembly_functional_tool_diameter,
obj.after_assembly_tool_loading_length, obj.after_assembly_knife_tip_r_angle,
round(obj.after_assembly_functional_tool_length, 3), obj.after_assembly_handle_length)
obj.code = '%s-%s' % (str_1, self._get_code(str_1))
str_1 = 'GNDJ-%s' % obj.after_assembly_functional_tool_type_id.code
str_2 = ''
if obj.handle_specification_id:
if obj.integral_specification_id:
str_2 = '%s-D%sL%sB%sH%s-' % (
str_1, obj.integral_specification_id.blade_diameter, obj.after_assembly_tool_loading_length,
obj.integral_specification_id.blade_length, obj.handle_specification_id.total_length)
elif obj.bar_specification_id:
str_2 = '%s-D%sL%sB%sH%s-' % (
str_1, obj.bar_specification_id.cutter_arbor_diameter, obj.after_assembly_tool_loading_length,
obj.bar_specification_id.blade_length, obj.handle_specification_id.total_length)
elif obj.pad_specification_id:
str_2 = '%s-D%sL%sB%sH%s-' % (
str_1, obj.pad_specification_id.cutter_head_diameter, obj.after_assembly_tool_loading_length,
obj.pad_specification_id.cut_depth_max, obj.handle_specification_id.total_length,
)
else:
obj.code = str_2
return True
obj.code = str_2 + str(self._get_code(str_2))
else:
obj.code = ''
obj.code = str_2
def _get_code(self, str_2):
functional_tool_assembly = self.env['sf.functional.cutting.tool.entity'].sudo().search(
@@ -574,7 +601,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
else:
obj.after_assembly_functional_tool_name = ''
@api.onchange('integral_freight_barcode_id')
@api.onchange('integral_freight_barcode')
def _onchange_after_assembly_functional_tool_diameter(self):
for obj in self:
if obj.integral_product_id:
@@ -582,7 +609,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
else:
obj.after_assembly_functional_tool_diameter = 0
@api.onchange('blade_freight_barcode_id')
@api.onchange('blade_freight_barcode')
def _onchange_after_assembly_knife_tip_r_angle(self):
for obj in self:
if obj.blade_product_id:
@@ -617,32 +644,25 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 创建组装入库单
# 创建功能刀具批次/序列号记录
stock_lot = product_id.create_assemble_warehouse_receipt(self.id, functional_tool_assembly, self)
# 封装功能刀具数据,用于更新组装单信息
desc_1 = self.get_desc_1(stock_lot)
# 封装功能刀具数据,用于创建功能刀具记录
desc_2 = self.get_desc_2(stock_lot, functional_tool_assembly)
# 创建刀具组装入库单
self.env['stock.picking'].create_stocking_picking(stock_lot, functional_tool_assembly, self)
# 刀具物料出库
if self.handle_code_id:
product_id.tool_material_stock_moves(self.handle_code_id, self.assembly_order_code)
if self.integral_product_id:
self.integral_product_id.material_stock_moves(self.integral_freight_barcode_id,
self.integral_freight_lot_id, self.assembly_order_code)
self.integral_product_id.material_stock_moves(self.integral_freight_barcode, self.assembly_order_code)
if self.blade_product_id:
self.blade_product_id.material_stock_moves(self.blade_freight_barcode_id,
self.blade_freight_lot_id, self.assembly_order_code)
self.blade_product_id.material_stock_moves(self.blade_freight_barcode, self.assembly_order_code)
if self.bar_product_id:
self.bar_product_id.material_stock_moves(self.bar_freight_barcode_id,
self.bar_freight_lot_id, self.assembly_order_code)
self.bar_product_id.material_stock_moves(self.bar_freight_barcode, self.assembly_order_code)
if self.pad_product_id:
self.pad_product_id.material_stock_moves(self.pad_freight_barcode_id,
self.pad_freight_lot_id, self.assembly_order_code)
self.pad_product_id.material_stock_moves(self.pad_freight_barcode, self.assembly_order_code)
if self.chuck_product_id:
self.chuck_product_id.material_stock_moves(self.chuck_freight_barcode_id,
self.chuck_freight_lot_id, self.assembly_order_code)
self.chuck_product_id.material_stock_moves(self.chuck_freight_barcode, self.assembly_order_code)
# ============================创建功能刀具列表、安全库存记录===============================
# 封装功能刀具数据
desc_2 = self.get_desc_2(stock_lot, functional_tool_assembly)
# 创建功能刀具列表记录
record_1 = self.env['sf.functional.cutting.tool.entity'].create(desc_2)
# 创建安全库存信息
@@ -651,6 +671,8 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
}, record_1)
# =====================修改功能刀具组装单、机床换刀申请、CAM工单程序用刀计划的状态==============
# 封装功能刀具数据
desc_1 = self.get_desc_1(stock_lot)
# 修改功能刀具组装单信息
functional_tool_assembly.write(desc_1)
if functional_tool_assembly.sf_machine_table_tool_changing_apply_id:
@@ -707,17 +729,12 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
'code': self.code,
'rfid': self.rfid,
'tool_groups_id': self.after_tool_groups_id.id,
'integral_freight_barcode': self.integral_freight_barcode,
'blade_freight_barcode': self.blade_freight_barcode,
'bar_freight_barcode': self.bar_freight_barcode,
'pad_freight_barcode': self.pad_freight_barcode,
'handle_code_id': self.handle_code_id.id,
'integral_freight_barcode_id': self.integral_freight_barcode_id.id,
'integral_lot_id': self.integral_freight_lot_id.lot_id.id,
'blade_freight_barcode_id': self.blade_freight_barcode_id.id,
'blade_lot_id': self.blade_freight_lot_id.lot_id.id,
'bar_freight_barcode_id': self.bar_freight_barcode_id.id,
'bar_lot_id': self.bar_freight_lot_id.lot_id.id,
'pad_freight_barcode_id': self.pad_freight_barcode_id.id,
'pad_lot_id': self.pad_freight_lot_id.lot_id.id,
'chuck_freight_barcode_id': self.chuck_freight_barcode_id.id,
'chuck_lot_id': self.chuck_freight_lot_id.lot_id.id,
'chuck_freight_barcode': self.chuck_freight_barcode,
'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,
@@ -798,7 +815,6 @@ class StockPicking(models.Model):
'picking_type_id': picking_type_id.id,
'location_id': picking_type_id.default_location_src_id.id,
'location_dest_id': picking_type_id.default_location_dest_id.id,
'origin': obj.assembly_order_code
})
# 创建作业详情对象记录,并绑定到刀具组装入库单
self.env['stock.move.line'].create({
@@ -849,7 +865,7 @@ class ProductProduct(models.Model):
logging.info('没有搜索到功能刀具产品:%s' % product_id)
raise ValidationError('没有找到按唯一序列号追溯的功能刀具产品信息!')
stock_lot = self.env['stock.lot'].create({
'name': self.get_stock_lot_name(obj),
'name': self.get_stock_lot_name(tool_assembly_order_id),
'product_id': product_id[0].id,
'company_id': self.env.company.id
})
@@ -862,21 +878,25 @@ class ProductProduct(models.Model):
return stock_lot
def get_stock_lot_name(self, obj):
def get_stock_lot_name(self, tool_assembly_order_id):
"""
生成功能刀具序列号
"""
company = obj.cutting_tool_cutterhandle_model_id.code.split('-', 1)[0]
tool_assembly_order = self.env['sf.functional.tool.assembly.order'].search(
[('id', '=', tool_assembly_order_id)])
code = 'JKM-T-' + str(tool_assembly_order.after_assembly_functional_tool_type_id.code) + '-' + str(
tool_assembly_order.after_assembly_functional_tool_diameter) + '-'
new_time = datetime.strptime(str(fields.Date.today()), "%Y-%m-%d").strftime("%Y%m%d")
code = '%s-GNDJ-%s-%s' % (company, obj.after_assembly_functional_tool_type_id.code, new_time)
code += str(new_time) + '-'
stock_lot_id = self.env['stock.lot'].sudo().search(
[('name', 'like', code)], limit=1, order="id desc")
[('name', 'like', new_time), ('product_id.categ_type', '=', '功能刀具'),
('product_id.tracking', '=', 'serial')], limit=1, order="id desc")
if not stock_lot_id:
num = "%03d" % 1
else:
m = int(stock_lot_id.name[-3:]) + 1
num = "%03d" % m
return '%s-%s' % (code, num)
return code + str(num)
def tool_material_stock_moves(self, tool_material, assembly_order_code):
"""
@@ -889,7 +909,7 @@ class ProductProduct(models.Model):
tool_material.create_stock_quant(location_inventory_id, stock_location_id, None, assembly_order_code, False,
False)
def material_stock_moves(self, shelf_location_barcode_id, lot_id, assembly_order_code):
def material_stock_moves(self, shelf_location_barcode, assembly_order_code):
# 创建库存移动记录
stock_move_id = self.env['stock.move'].sudo().create({
'name': assembly_order_code,
@@ -900,16 +920,21 @@ class ProductProduct(models.Model):
'state': 'done'
})
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', shelf_location_barcode)])
# 创建移动历史记录
stock_move_line_id = self.env['stock.move.line'].sudo().create({
'product_id': self.id,
'move_id': stock_move_id.id,
'lot_id': lot_id.lot_id.id,
'current_location_id': shelf_location_barcode_id.id,
'current_location_id': location.id,
'install_tool_time': fields.Datetime.now(),
'qty_done': 1.0,
'state': 'done',
})
if location.product_num > 0:
location.product_num = location.product_num - 1
else:
raise ValidationError(
'%s】货位的【%s】产品库存数量为零,请采购入库后再重新组装!' % (location.barcode, location.product_id.name))
return stock_move_id, stock_move_line_id

View File

@@ -229,18 +229,13 @@
</group>
</group>
<group col="1"
attrs="{'invisible': ['|','|',('blade_freight_barcode_id', '!=', False),('bar_freight_barcode_id', '!=', False),('pad_freight_barcode_id', '!=', False)]}">
attrs="{'invisible': ['|','|',('blade_freight_barcode', '!=', False),('bar_freight_barcode', '!=', False),('pad_freight_barcode', '!=', False)]}">
<div>
<separator string="整体式刀具:" style="font-size: 13px;"/>
</div>
<group>
<group>
<field name="integral_freight_barcode_id" options="{'no_create': True}"
placeholder="请选择" string="货位"/>
</group>
<group>
<field name="integral_freight_lot_id" options="{'no_create': True}"
placeholder="请选择" string="批次"/>
<field name="integral_freight_barcode" string="货位"/>
</group>
</group>
<group col="2">
@@ -254,18 +249,13 @@
</group>
</group>
</group>
<group col="1" attrs="{'invisible': [('integral_freight_barcode_id', '!=', False)]}">
<group col="1" attrs="{'invisible': [('integral_freight_barcode', '!=', False)]}">
<div>
<separator string="刀片:" style="font-size: 13px;"/>
</div>
<group>
<group>
<field name="blade_freight_barcode_id" options="{'no_create': True}"
placeholder="请选择" string="货位"/>
</group>
<group>
<field name="blade_freight_lot_id" options="{'no_create': True}"
placeholder="请选择" string="批次"/>
<field name="blade_freight_barcode" string="货位"/>
</group>
</group>
<group col="2">
@@ -280,18 +270,13 @@
</group>
</group>
<group col="1"
attrs="{'invisible': ['|',('integral_freight_barcode_id', '!=', False),('pad_freight_barcode_id', '!=', False)]}">
attrs="{'invisible': ['|',('integral_freight_barcode', '!=', False),('pad_freight_barcode', '!=', False)]}">
<div>
<separator string="刀杆:" style="font-size: 13px;"/>
</div>
<group>
<group>
<field name="bar_freight_barcode_id" options="{'no_create': True}"
placeholder="请选择" string="货位"/>
</group>
<group>
<field name="bar_freight_lot_id" options="{'no_create': True}" placeholder="请选择"
string="批次"/>
<field name="bar_freight_barcode" string="货位"/>
</group>
</group>
<group col="2">
@@ -306,18 +291,13 @@
</group>
</group>
<group col="1"
attrs="{'invisible': ['|',('integral_freight_barcode_id', '!=', False),('bar_freight_barcode_id', '!=', False)]}">
attrs="{'invisible': ['|',('integral_freight_barcode', '!=', False),('bar_freight_barcode', '!=', False)]}">
<div>
<separator string="刀盘:" style="font-size: 13px;"/>
</div>
<group>
<group>
<field name="pad_freight_barcode_id" options="{'no_create': True}"
placeholder="请选择" string="货位"/>
</group>
<group>
<field name="pad_freight_lot_id" options="{'no_create': True}" placeholder="请选择"
string="批次"/>
<field name="pad_freight_barcode" string="货位"/>
</group>
</group>
<group col="2">
@@ -337,12 +317,7 @@
</div>
<group>
<group>
<field name="chuck_freight_barcode_id" options="{'no_create': True}"
placeholder="请选择" string="货位"/>
</group>
<group>
<field name="chuck_freight_lot_id" options="{'no_create': True}"
placeholder="请选择" string="批次"/>
<field name="chuck_freight_barcode" string="货位"/>
</group>
</group>
<group col="2">
@@ -368,14 +343,12 @@
<group>
<field name="obtain_measurement_status" invisible="1"/>
<button name="get_tool_preset_parameter" string="获取测量值" type="object"
attrs="{'invisible': [('enable_tool_presetter', '=', False)]}"
class="btn-primary"/>
</group>
</group>
<group>
<group>
<field name="after_name_id" string="功能刀具名称" placeholder="请选择功能刀具名称"
readonly="1"
<field name="after_name_id" string="功能刀具名称" placeholder="请选择功能刀具名称" readonly="1"
options="{'no_create': True, 'no_quick_create': True}"/>
<field name="after_assembly_functional_tool_name" string="功能刀具名称"
invisible="1"/>
@@ -394,16 +367,12 @@
attrs="{'invisible': [('after_assembly_new_former','=','0')]}"/>
</group>
<group>
<field name="enable_tool_presetter" invisible="1"/>
<field name="after_assembly_functional_tool_diameter" string="刀具直径(mm)"
attrs="{'readonly': [('enable_tool_presetter', '=', True)]}"
class="custom_required"/>
class="custom_required" readonly="1"/>
<field name="after_assembly_knife_tip_r_angle" string="刀尖R角(mm)"
attrs="{'readonly': [('enable_tool_presetter', '=', True)]}"
class="custom_required"/>
class="custom_required" readonly="1"/>
<field name="after_assembly_tool_loading_length" string="总长度(mm)"
attrs="{'readonly': [('enable_tool_presetter', '=', True)]}"
class="custom_required"/>
class="custom_required" readonly="1"/>
<field name="after_assembly_handle_length" string="刀柄长度(mm)"
class="custom_required"/>
<field name="after_assembly_functional_tool_length" string="伸出长(mm)"
@@ -423,7 +392,7 @@
</sheet>
<footer>
<button string="确定" name="functional_tool_assembly" type="object" class="btn-primary"
attrs="{'invisible': [('obtain_measurement_status', '=', False),('enable_tool_presetter', '=', True)]}"
attrs="{'invisible': [('obtain_measurement_status', '=', False)]}"
confirm="是否确认申请组装"/>
<button string="取消" class="btn-secondary" special="cancel"/>
</footer>

View File

@@ -416,19 +416,19 @@ class ShelfLocation(models.Model):
host = printer_config.printer_id.ip_address
port = printer_config.printer_id.port
self.print_qr_code(barcode, host, port)
# 获取当前wizard的视图ID或其他标识信息
view_id = self.env.context.get('view_id')
# 构造返回wizard页面的action字典
action = {
'type': 'ir.actions.act_window',
'name': '返回 Wizard',
'res_model': 'sf.shelf', # 替换为你的wizard模型名称
'view_mode': 'form',
'view_id': view_id, # 如果需要基于特定的视图返回
'target': 'new', # 如果需要在新的窗口或标签页打开
'res_id': self.shelf_id, # 如果你想要返回当前记录的视图
}
return action
# # 获取当前wizard的视图ID或其他标识信息
# view_id = self.env.context.get('view_id')
# # 构造返回wizard页面的action字典
# action = {
# 'type': 'ir.actions.act_window',
# 'name': '返回 Wizard',
# 'res_model': 'sf.shelf', # 替换为你的wizard模型名称
# 'view_mode': 'form',
# 'view_id': view_id, # 如果需要基于特定的视图返回
# 'target': 'new', # 如果需要在新的窗口或标签页打开
# 'res_id': self.shelf_id, # 如果你想要返回当前记录的视图
# }
# return action
# # 仓库类别selection库区、库位、货位
# location_type = fields.Selection([
@@ -452,9 +452,8 @@ class ShelfLocation(models.Model):
# 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_sn_ids = fields.One2many('sf.shelf.location.lot', 'shelf_location_id', string='产品批次号')
# 产品数量
product_num = fields.Integer('数量', compute='_compute_number', store=True)
product_num = fields.Integer('数量')
@api.depends('product_num')
def _compute_product_num(self):
@@ -464,15 +463,6 @@ class ShelfLocation(models.Model):
elif record.product_num == 0:
record.location_status = '空闲'
@api.depends('product_sn_ids.qty')
def _compute_number(self):
for item in self:
if item.product_sn_ids:
qty = 0
for product_sn_id in item.product_sn_ids:
qty += product_sn_id.qty
item.product_num = qty
# 修改货位状态为禁用
def action_location_status_disable(self):
self.location_status = '禁用'
@@ -481,7 +471,7 @@ class ShelfLocation(models.Model):
def action_location_status_enable(self):
self.location_status = '空闲'
@api.depends('product_sn_id', 'product_sn_ids')
@api.depends('product_sn_id')
def _compute_product_id(self):
"""
根据产品序列号,获取产品
@@ -494,8 +484,7 @@ class ShelfLocation(models.Model):
record.sudo().product_num = 1
except Exception as e:
print('eeeeeee占用', e)
elif record.product_sn_ids:
return True
else:
try:
record.sudo().product_id = False
@@ -536,24 +525,7 @@ class ShelfLocation(models.Model):
return records
class SfShelfLocationLot(models.Model):
_name = 'sf.shelf.location.lot'
_description = '批次数量'
name = fields.Char('名称', related='lot_id.name')
shelf_location_id = fields.Many2one('sf.shelf.location', string="货位")
lot_id = fields.Many2one('stock.lot', string='批次号')
qty = fields.Integer('数量')
qty_num = fields.Integer('变更数量')
@api.onchange('qty_num')
def _onchange_qty_num(self):
for item in self:
if item.qty_num > item.qty:
raise ValidationError('变更数量不能比库存数量大!!!')
class SfStockMoveLine(models.Model):
class Sf_stock_move_line(models.Model):
_name = 'stock.move.line'
_inherit = ['stock.move.line', 'printing.utils']
@@ -853,20 +825,15 @@ class SfStockMoveLine(models.Model):
obj = self.env['sf.shelf.location'].search([('name', '=',
self.destination_location_id.name)])
if record.lot_id:
if record.product_id.tracking == 'serial':
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
if obj:
obj.product_sn_id = record.lot_id.id
else:
if obj:
obj.product_sn_id = record.lot_id.id
elif record.product_id.tracking == 'lot':
self.put_shelf_location(record)
if not obj.product_id:
obj.product_id = record.product_id.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
if obj:
obj.product_sn_id = record.lot_id.id
else:
if obj:
obj.product_sn_id = record.lot_id.id
else:
if obj:
obj.product_id = record.product_id.id
@@ -886,47 +853,6 @@ class SfStockMoveLine(models.Model):
raise ValidationError(
'%s】货位已经被占用,请重新选择!!!' % item.destination_location_id.barcode)
def put_shelf_location(self, vals):
"""
对货位的批量数据进行数量计算
"""
for record in vals:
if record.lot_id and record.product_id.tracking == 'lot':
if record.current_location_id:
location_lot = self.env['sf.shelf.location.lot'].sudo().search(
[('shelf_location_id', '=', record.current_location_id.id), ('lot_id', '=', record.lot_id.id)])
if location_lot:
location_lot.qty -= record.qty_done
if location_lot.qty == 0:
location_lot.unlink()
elif location_lot.qty < 0:
raise ValidationError('%s】货位【%s】批次的【%s】产品数量不足!' % (
record.current_location_id.barcode, record.lot_id.name, record.product_id.name))
else:
raise ValidationError('%s】货位不存在【%s】批次的【%s】产品' % (
record.current_location_id.barcode, record.lot_id.name, record.product_id.name))
if record.destination_location_id:
location_lot = self.env['sf.shelf.location.lot'].sudo().search(
[('shelf_location_id', '=', record.destination_location_id.id),
('lot_id', '=', record.lot_id.id)])
if location_lot:
location_lot.qty += record.qty_done
else:
self.env['sf.shelf.location.lot'].sudo().create({
'shelf_location_id': record.destination_location_id.id,
'lot_id': record.lot_id.id,
'qty': record.qty_done
})
if not record.destination_location_id.product_id:
record.destination_location_id.product_id = record.product_id.id
@api.model_create_multi
def create(self, vals_list):
records = super(SfStockMoveLine, self).create(vals_list)
self.put_shelf_location(records)
return records
class SfStockPicking(models.Model):
_inherit = 'stock.picking'
@@ -990,9 +916,6 @@ class SfStockPicking(models.Model):
if move and move.product_id.cutting_tool_material_id.name == '刀柄' or '托盘' in (
move.product_id.fixture_material_id.name or ''):
for item in move.move_line_nosuggest_ids:
if item.rfid:
if self.env['stock.lot'].search([('rfid', '=', item.rfid)]):
raise ValidationError('该Rfid【%s】在系统中已经存在,请重新录入!' % item.rfid)
if item.location_dest_id.name == '进货':
if not item.rfid:
raise ValidationError('你需要提供%s的Rfid' % move.product_id.name)

View File

@@ -95,34 +95,17 @@ class MrsShelfLocationDataSync(models.Model):
return code_pair[0]
return None # 如果没有找到对应的值返回None或适当的默认值
# 定时更新所有设备机床刀库信息
equipment_ids = self.env['maintenance.equipment'].search(
[('equipment_type', '=', '机床'), ('function_type', '!=', False)])
for equipment_id in equipment_ids:
if equipment_id:
equipment_id.register_equipment_tool()
shelfinfo = self.env['sf.shelf.location'].get_sf_shelf_location_info()
print('shelfinfo:', shelfinfo)
for item in shelfinfo:
shelf_barcode = find_our_code(item['Postion'], total_data)
location_id = self.env['sf.shelf.location'].search([('barcode', '=', shelf_barcode)], limit=1)
if location_id:
# 如果是线边刀库信息,则对功能刀具移动生成记录
if 'Tool' in item['Postion']:
tool = self.env['sf.functional.cutting.tool.entity'].sudo().search(
[('rfid', '=', item['RfidCode']), ('functional_tool_status', '!=', '已拆除')])
tool.tool_in_out_stock_location(location_id)
if tool:
location_id.product_sn_id = tool.barcode_id.id
else:
location_id.product_sn_id = False
stock_lot_obj = self.env['stock.lot'].search([('rfid', '=', item['RfidCode'])], limit=1)
if stock_lot_obj:
location_id.product_sn_id = stock_lot_obj.id
else:
stock_lot_obj = self.env['stock.lot'].search([('rfid', '=', item['RfidCode'])], limit=1)
if stock_lot_obj:
location_id.product_sn_id = stock_lot_obj.id
else:
location_id.product_sn_id = False
location_id.product_sn_id = False
logging.info('货架已获取信息:%s' % item)
except Exception as e:

View File

@@ -1,9 +1,7 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sf_shelf_location_group_sf_stock_user_group_sf_stock_user,sf.shelf.location,model_sf_shelf_location,sf_base.group_sf_stock_user,1,0,0,0
access_sf_shelf_location_lot_group_sf_stock_user_group_sf_stock_user,sf.shelf.location.lot,model_sf_shelf_location_lot,sf_base.group_sf_stock_user,1,0,0,0
access_sf_shelf_location_group_sf_stock_manager,sf.shelf.location,model_sf_shelf_location,sf_base.group_sf_stock_manager,1,1,1,0
access_sf_shelf_location_lot_group_sf_stock_manager,sf.shelf.location.lot,model_sf_shelf_location_lot,sf_base.group_sf_stock_manager,1,1,1,0
access_sf_shelf_group_sf_stock_user_group_sf_stock_user,sf.shelf.group.sf.stock.user,model_sf_shelf,sf_base.group_sf_stock_user,1,0,0,0
access_sf_shelf_group_sf_stock_manager,sf.shelf.group.sf.stock.manager,model_sf_shelf,sf_base.group_sf_stock_manager,1,1,1,0
@@ -103,7 +101,6 @@ access_stock_replenish_option_group_sf_stock_user,stock.replenishment.option,sto
access_mrp_production_group_sf_stock_user,mrp.production,mrp.model_mrp_production,sf_base.group_sf_stock_user,1,1,1,0
access_sf_shelf_location_group_plan_dispatch,sf.shelf.location,model_sf_shelf_location,sf_base.group_plan_dispatch,1,0,0,0
access_sf_shelf_location_lot_group_plan_dispatch,sf.shelf.location.lot,model_sf_shelf_location_lot,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_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
@@ -145,9 +142,6 @@ access_sf_shelf_location_wizard_group_sf_stock_manager,sf_shelf_location_wizard_
access_sf_shelf_location_group_sf_tool_user,sf.shelf.location.group_sf_tool_user,model_sf_shelf_location,sf_base.group_sf_tool_user,1,1,0,0
access_sf_shelf_group_user,sf.shelf.location.group_user,model_sf_shelf_location,base.group_user,1,1,0,0
access_sf_shelf_location_lot_group_sf_tool_user,sf.shelf.location.lot.group_sf_tool_user,model_sf_shelf_location_lot,sf_base.group_sf_tool_user,1,1,0,0
access_sf_shelf_lot_group_user,sf.shelf.location.lot.group_user,model_sf_shelf_location_lot,base.group_user,1,1,0,0
access_ir_model_group_sf_stock_user,ir_model_group_sf_stock_user,base.model_ir_model,sf_base.group_sf_stock_user,1,1,0,0
access_mrp_workorder_group_sf_stock_user,mrp_workorder_group_sf_stock_user,mrp.model_mrp_workorder,sf_base.group_sf_stock_user,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sf_shelf_location_group_sf_stock_user_group_sf_stock_user sf.shelf.location model_sf_shelf_location sf_base.group_sf_stock_user 1 0 0 0
3 access_sf_shelf_location_lot_group_sf_stock_user_group_sf_stock_user access_sf_shelf_location_group_sf_stock_manager sf.shelf.location.lot sf.shelf.location model_sf_shelf_location_lot model_sf_shelf_location sf_base.group_sf_stock_user sf_base.group_sf_stock_manager 1 0 1 0 1 0
access_sf_shelf_location_group_sf_stock_manager sf.shelf.location model_sf_shelf_location sf_base.group_sf_stock_manager 1 1 1 0
4 access_sf_shelf_location_lot_group_sf_stock_manager access_sf_shelf_group_sf_stock_user_group_sf_stock_user sf.shelf.location.lot sf.shelf.group.sf.stock.user model_sf_shelf_location_lot model_sf_shelf sf_base.group_sf_stock_manager sf_base.group_sf_stock_user 1 1 0 1 0 0
access_sf_shelf_group_sf_stock_user_group_sf_stock_user sf.shelf.group.sf.stock.user model_sf_shelf sf_base.group_sf_stock_user 1 0 0 0
5 access_sf_shelf_group_sf_stock_manager sf.shelf.group.sf.stock.manager model_sf_shelf sf_base.group_sf_stock_manager 1 1 1 0
6 access_procurement_group procurement.group stock.model_procurement_group base.group_user 1 1 1 0
7 access_stock_warehouse_manager_group_sf_stock_user stock.warehouse.manager stock.model_stock_warehouse sf_base.group_sf_stock_user 1 1 1 0
101 access_stock_move access_stock_picking_group_plan_dispatch stock.move stock.picking stock.model_stock_move stock.model_stock_picking sf_base.group_plan_dispatch 1 1 0 1 0 0
102 access_stock_picking_group_plan_dispatch access_stock_lot_group_plan_dispatch stock.picking stock.lot stock.model_stock_picking stock.model_stock_lot sf_base.group_plan_dispatch 1 0 0 0
103 access_stock_lot_group_plan_dispatch access_stock_lot_group_plan_director stock.lot stock.model_stock_lot sf_base.group_plan_dispatch sf_base.group_plan_director 1 0 1 0 1 0
access_stock_lot_group_plan_director stock.lot stock.model_stock_lot sf_base.group_plan_director 1 1 1 0
104 access_stock_warehouse_orderpoint stock.warehouse.orderpoint stock.model_stock_warehouse_orderpoint sf_base.group_plan_dispatch 1 1 0 0
105 access_stock_inventory_conflict stock.inventory.conflict stock.model_stock_inventory_conflict sf_base.group_plan_dispatch 1 0 0 0
106 access_stock_inventory_warning stock.inventory.warning stock.model_stock_inventory_warning sf_base.group_plan_dispatch 1 0 0 0
142
143
144
145
146
147

View File

@@ -133,11 +133,9 @@
type="action"
context="{'default_name':name,
'default_current_name':name,
'default_current_product_sn_ids':product_sn_ids,
'default_lot_id':product_sn_id,
'default_current_shelf_id':shelf_id,
'default_current_location_id':location_id,
'default_current_barcode_id':id,
'default_current_barcode':barcode,
'default_current_product_id':product_id,
}"
class="btn-primary" attrs="{'invisible':[('location_status','!=','占用')]}"/>
@@ -171,16 +169,8 @@
<field name="name" readonly="1"/>
<field name="shelf_id" readonly="1"/>
<field name="location_id" readonly="1"/>
<field name="product_sn_id" options="{'no_create': True}"/>
<field name="product_id"/>
<field name="product_sn_id" options="{'no_create': True}"
attrs="{'invisible': [('product_sn_ids', '!=', [])]}"/>
<field name="product_sn_ids"
attrs="{'invisible': [('product_sn_ids', '=', [])]}">
<tree edit="1" create="0" delete="0" editable="bottom">
<field name="lot_id" readonly="1"/>
<field name="qty" readonly="1"/>
</tree>
</field>
<field name="product_num" readonly="1"/>
<field name="location_status"/>
<field name="storage_time" widget="datetime"/>

View File

@@ -8,23 +8,17 @@ class ShelfLocationWizard(models.TransientModel):
name = fields.Char('')
lot_id = fields.Many2one('stock.lot', string="序列号", readonly=True)
current_location_id = fields.Many2one('stock.location', string='所属库区', readonly=True)
current_shelf_id = fields.Many2one('sf.shelf', string='当前货架', readonly=True)
current_barcode_id = fields.Many2one('sf.shelf.location', string='当前货位编码', readonly=True)
current_barcode = fields.Char('当前货位编码', readonly=True)
current_name = fields.Char('当前货位名称', readonly=True)
current_product_id = fields.Many2one('product.product', string='产品', readonly=True)
current_product_sn_ids = fields.Many2many('sf.shelf.location.lot', 'shelf_location_wizard', string='产品批次号',
readonly=True)
destination_location_id = fields.Many2one('stock.location', string='目标库区', compute='_compute_destination_name')
destination_shelf_id = fields.Many2one('sf.shelf', string='目标货架', compute='_compute_destination_name')
destination_barcode_id = fields.Many2one('sf.shelf.location', string='目标货位编码', required=True,
domain="[('product_id', 'in', (False, current_product_id))]")
domain="")
destination_name = fields.Char('目标货位名称', compute='_compute_destination_name')
destination_product_sn_ids = fields.Many2many('sf.shelf.location.lot', 'shelf_location_wizard', string='批次号',
domain="[('shelf_location_id', '=', current_barcode_id)]")
def return_domain(self):
val = [('location_status', '=', '空闲')]
@@ -38,11 +32,9 @@ class ShelfLocationWizard(models.TransientModel):
def _compute_destination_name(self):
if self.destination_barcode_id:
self.destination_name = self.destination_barcode_id.name
self.destination_location_id = self.destination_barcode_id.location_id.id
self.destination_shelf_id = self.destination_barcode_id.shelf_id.id
else:
self.destination_name = ''
self.destination_location_id = False
self.destination_shelf_id = False
#
@@ -51,46 +43,22 @@ class ShelfLocationWizard(models.TransientModel):
# if self.destination_barcode_id:
# self.destination_shelf_id = self.destination_barcode_id.shelf_id.id
def create_stock_moves(self, lot_id, num):
# 创建产品货位变更的库存移动记录
stock_move_id = self.env['stock.move'].sudo().create({
'name': 'HWBG/%s' % self.id,
'product_id': self.current_product_id.id,
'location_id': self.current_location_id.id,
'location_dest_id': self.destination_location_id.id,
'product_uom_qty': num,
'state': 'done'
})
# 创建移动历史记录
stock_move_line_id = self.env['stock.move.line'].sudo().create({
'product_id': self.current_product_id.id,
'lot_id': lot_id.id,
'move_id': stock_move_id.id,
'current_location_id': self.current_barcode_id.id,
'destination_location_id': self.destination_barcode_id.id,
'install_tool_time': fields.Datetime.now(),
'qty_done': num,
'state': 'done'
})
return stock_move_id, stock_move_line_id
def confirm_the_change(self):
if self.destination_barcode_id:
if self.lot_id:
self.current_barcode_id.product_sn_id = False
self.destination_barcode_id.product_sn_id = self.lot_id.id
self.create_stock_moves(self.lot_id, 1)
elif self.current_product_sn_ids:
for current_product_sn_id in self.current_product_sn_ids:
self.create_stock_moves(current_product_sn_id.lot_id, current_product_sn_id.qty_num)
current_product_sn_id.write({
'qty_num': 0
})
shelf_location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.current_barcode)])
# 变更货位
if self.destination_barcode_id and shelf_location:
if self.destination_barcode_id.product_id and self.destination_barcode_id.product_id == shelf_location.product_id and not self.destination_barcode_id.product_sn_id:
self.destination_barcode_id.product_num += shelf_location.product_num
else:
raise ValidationError('没有需要变更的批次/序列号!')
self.destination_barcode_id.product_sn_id = shelf_location.product_sn_id.id
self.destination_barcode_id.product_id = shelf_location.product_id.id
self.destination_barcode_id.product_num = shelf_location.product_num
shelf_location.product_sn_id = False
shelf_location.product_id = False
shelf_location.product_num = 0
else:
raise ValidationError('请选择目标货位编码!')
raise ValidationError('目标货位出错,请联系管理员!')
# 关闭弹出窗口
return {'type': 'ir.actions.act_window_close'}

View File

@@ -6,45 +6,27 @@
<field name="arch" type="xml">
<form string="货位变更">
<sheet>
<group col="1">
<group>
<group string="初始货位">
<group>
<field name="current_location_id"/>
<field name="current_shelf_id" string="货架"/>
<field name="current_barcode" string="编码"/>
<field name="current_name" string="名称"/>
</group>
<group>
<field name="current_barcode_id" string="编码"/>
<field name="lot_id" attrs="{'invisible': [('lot_id', '=', False)]}"/>
</group>
<field name="current_product_sn_ids"
attrs="{'invisible': [('current_product_sn_ids', '=', [])]}">
<tree edit="1" create="0" delete="0" editable="bottom">
<field name="lot_id" readonly="1"/>
<field name="qty" readonly="1"/>
</tree>
</field>
</group>
<group string="目标货位">
<group>
<field name="destination_location_id"/>
<field name="destination_shelf_id" string="货架" options="{'no_create': True}"/>
<field name="current_location_id"/>
<field name="destination_shelf_id" string="货架" options="{'no_create': True}"
placeholder="请选择目标货架"/>
<field name="destination_barcode_id" string="编码" options="{'no_create': True}"
placeholder="请选择目标货位"
domain="['|', ('location_status', '=', '空闲'), ('product_id', '=', current_product_id)]"/>
<field name="destination_name" string="名称"/>
<field name="current_product_id" invisible="1"/>
</group>
<group>
<field name="destination_barcode_id" string="编码" options="{'no_create': True}"
placeholder="请选择目标货位"/>
<field name="lot_id" attrs="{'invisible': [('lot_id', '=', False)]}"/>
</group>
</group>
<field name="destination_product_sn_ids"
attrs="{'invisible': [('current_product_sn_ids', '=', [])]}">
<tree edit="1" create="0" delete="1" editable="bottom">
<field name="lot_id" readonly="1"/>
<field name="qty_num"/>
</tree>
</field>
</group>
</sheet>
<footer>