Compare commits
41 Commits
release_1.
...
38e99a0f26
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38e99a0f26 | ||
|
|
741c5cf3d6 | ||
|
|
fa7e023dd1 | ||
|
|
a3580411d6 | ||
|
|
d7779cdb58 | ||
|
|
adafce85bd | ||
|
|
7be5b53767 | ||
|
|
8c285c0eb5 | ||
|
|
22e24c5ed3 | ||
|
|
4459ed2e81 | ||
|
|
52bf899a1f | ||
|
|
002727070d | ||
|
|
81327f04de | ||
|
|
e8c86c6306 | ||
|
|
fd6b579e2a | ||
|
|
0b2b162d85 | ||
|
|
2eaec4fa58 | ||
|
|
e306d02ff2 | ||
|
|
09c56b2c07 | ||
|
|
f4926820fe | ||
|
|
5361fa7678 | ||
|
|
edf8e1004e | ||
|
|
17e2a3ffc3 | ||
|
|
e258e43b51 | ||
|
|
1af160542c | ||
|
|
71246af16a | ||
|
|
d2f4e5495e | ||
|
|
ba2b833aa8 | ||
|
|
cf0afd6c64 | ||
|
|
e290760895 | ||
|
|
19799aefe4 | ||
|
|
8bd5841d7a | ||
|
|
6fc94042ee | ||
|
|
711e0d1437 | ||
|
|
ea6de0c248 | ||
|
|
d213a2cf54 | ||
|
|
a1d8b88db2 | ||
|
|
7ab954ebbc | ||
|
|
fe88a416a7 | ||
|
|
6dc29fb50a | ||
|
|
412bf4b9be |
@@ -521,4 +521,9 @@ div:has(.o_required_modifier) > label::before {
|
||||
.o_list_renderer.o_renderer {
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
// 设置表单页面label文本不换行
|
||||
.o_form_view .o_group .o_wrap_label .o_form_label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -27,7 +27,7 @@ class MrpWorkcenter(models.Model):
|
||||
|
||||
class MrpProductionWorkcenterLine(models.Model):
|
||||
_name = 'mrp.workorder'
|
||||
_inherit = ['mrp.workorder', 'barcodes.barcode_events_mixin']
|
||||
_inherit = ['mrp.workorder', 'barcodes.barcode_events_mixin', 'mail.thread', 'mail.activity.mixin']
|
||||
|
||||
quality_point_ids = fields.Many2many('quality.point', compute='_compute_quality_point_ids', store=True)
|
||||
quality_point_count = fields.Integer('Steps', compute='_compute_quality_point_count')
|
||||
@@ -47,14 +47,17 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
|
||||
is_last_lot = fields.Boolean('Is Last lot', compute='_compute_is_last_lot')
|
||||
is_first_started_wo = fields.Boolean('Is The first Work Order', compute='_compute_is_last_unfinished_wo')
|
||||
is_last_unfinished_wo = fields.Boolean('Is Last Work Order To Process', compute='_compute_is_last_unfinished_wo', store=False)
|
||||
is_last_unfinished_wo = fields.Boolean('Is Last Work Order To Process', compute='_compute_is_last_unfinished_wo',
|
||||
store=False)
|
||||
lot_id = fields.Many2one(related='current_quality_check_id.lot_id', readonly=False)
|
||||
move_id = fields.Many2one(related='current_quality_check_id.move_id', readonly=False)
|
||||
move_line_id = fields.Many2one(related='current_quality_check_id.move_line_id', readonly=False)
|
||||
move_line_ids = fields.One2many(related='move_id.move_line_ids')
|
||||
quality_state = fields.Selection(related='current_quality_check_id.quality_state', string="Quality State", readonly=False)
|
||||
quality_state = fields.Selection(related='current_quality_check_id.quality_state', string="Quality State",
|
||||
readonly=False)
|
||||
qty_done = fields.Float(related='current_quality_check_id.qty_done', readonly=False)
|
||||
test_type_id = fields.Many2one('quality.point.test_type', 'Test Type', related='current_quality_check_id.test_type_id')
|
||||
test_type_id = fields.Many2one('quality.point.test_type', 'Test Type',
|
||||
related='current_quality_check_id.test_type_id')
|
||||
test_type = fields.Char(related='test_type_id.technical_name')
|
||||
user_id = fields.Many2one(related='current_quality_check_id.user_id', readonly=False)
|
||||
worksheet_page = fields.Integer('Worksheet page')
|
||||
@@ -65,7 +68,8 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
def _compute_quality_point_ids(self):
|
||||
for workorder in self:
|
||||
quality_points = workorder.operation_id.quality_point_ids
|
||||
quality_points = quality_points.filtered(lambda qp: not qp.product_ids or workorder.production_id.product_id in qp.product_ids)
|
||||
quality_points = quality_points.filtered(
|
||||
lambda qp: not qp.product_ids or workorder.production_id.product_id in qp.product_ids)
|
||||
workorder.quality_point_ids = quality_points
|
||||
|
||||
@api.depends('operation_id')
|
||||
@@ -91,7 +95,8 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
@api.depends('check_ids')
|
||||
def _compute_finished_product_check_ids(self):
|
||||
for wo in self:
|
||||
wo.finished_product_check_ids = wo.check_ids.filtered(lambda c: c.finished_product_sequence == wo.qty_produced)
|
||||
wo.finished_product_check_ids = wo.check_ids.filtered(
|
||||
lambda c: c.finished_product_sequence == wo.qty_produced)
|
||||
|
||||
def write(self, values):
|
||||
res = super().write(values)
|
||||
@@ -138,7 +143,8 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
self.finished_lot_id = self.env['stock.lot'].create({
|
||||
'product_id': self.product_id.id,
|
||||
'company_id': self.company_id.id,
|
||||
'name': self.env['stock.lot']._get_next_serial(self.company_id, self.product_id) or self.env['ir.sequence'].next_by_code('stock.lot.serial'),
|
||||
'name': self.env['stock.lot']._get_next_serial(self.company_id, self.product_id) or self.env[
|
||||
'ir.sequence'].next_by_code('stock.lot.serial'),
|
||||
})
|
||||
|
||||
def _create_subsequent_checks(self):
|
||||
@@ -152,7 +158,7 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
"""
|
||||
# Create another quality check if necessary
|
||||
next_check = self.current_quality_check_id.next_check_id
|
||||
if next_check.component_id != self.current_quality_check_id.product_id or\
|
||||
if next_check.component_id != self.current_quality_check_id.product_id or \
|
||||
next_check.point_id != self.current_quality_check_id.point_id:
|
||||
# TODO: manage reservation here
|
||||
|
||||
@@ -279,7 +285,8 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
if self.current_quality_check_id:
|
||||
team = self.current_quality_check_id.team_id
|
||||
else:
|
||||
team = self.env['quality.alert.team'].search(['|', ('company_id', '=', self.company_id.id), ('company_id', '=', False)], limit=1)
|
||||
team = self.env['quality.alert.team'].search(
|
||||
['|', ('company_id', '=', self.company_id.id), ('company_id', '=', False)], limit=1)
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'quality.check',
|
||||
@@ -320,7 +327,8 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
production = wo.production_id
|
||||
|
||||
move_raw_ids = wo.move_raw_ids.filtered(lambda m: m.state not in ('done', 'cancel'))
|
||||
move_finished_ids = wo.move_finished_ids.filtered(lambda m: m.state not in ('done', 'cancel') and m.product_id != wo.production_id.product_id)
|
||||
move_finished_ids = wo.move_finished_ids.filtered(
|
||||
lambda m: m.state not in ('done', 'cancel') and m.product_id != wo.production_id.product_id)
|
||||
previous_check = self.env['quality.check']
|
||||
for point in wo.quality_point_ids:
|
||||
# Check if we need a quality control for this point
|
||||
@@ -342,11 +350,13 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
if point.test_type == 'register_byproducts':
|
||||
moves = move_finished_ids.filtered(lambda m: m.product_id == point.component_id)
|
||||
if not moves:
|
||||
moves = production.move_finished_ids.filtered(lambda m: not m.operation_id and m.product_id == point.component_id)
|
||||
moves = production.move_finished_ids.filtered(
|
||||
lambda m: not m.operation_id and m.product_id == point.component_id)
|
||||
elif point.test_type == 'register_consumed_materials':
|
||||
moves = move_raw_ids.filtered(lambda m: m.product_id == point.component_id)
|
||||
if not moves:
|
||||
moves = production.move_raw_ids.filtered(lambda m: not m.operation_id and m.product_id == point.component_id)
|
||||
moves = production.move_raw_ids.filtered(
|
||||
lambda m: not m.operation_id and m.product_id == point.component_id)
|
||||
else:
|
||||
check = self.env['quality.check'].create(values)
|
||||
previous_check.next_check_id = check
|
||||
@@ -363,8 +373,10 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
processed_move |= moves
|
||||
|
||||
# Generate quality checks associated with unreferenced components
|
||||
moves_without_check = ((move_raw_ids | move_finished_ids) - processed_move).filtered(lambda move: (move.has_tracking != 'none' and not move.raw_material_production_id.use_auto_consume_components_lots) or move.operation_id)
|
||||
quality_team_id = self.env['quality.alert.team'].search(['|', ('company_id', '=', wo.company_id.id), ('company_id', '=', False)], limit=1).id
|
||||
moves_without_check = ((move_raw_ids | move_finished_ids) - processed_move).filtered(lambda move: (
|
||||
move.has_tracking != 'none' and not move.raw_material_production_id.use_auto_consume_components_lots) or move.operation_id)
|
||||
quality_team_id = self.env['quality.alert.team'].search(
|
||||
['|', ('company_id', '=', wo.company_id.id), ('company_id', '=', False)], limit=1).id
|
||||
for move in moves_without_check:
|
||||
values = {
|
||||
'production_id': production.id,
|
||||
@@ -412,7 +424,8 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
|
||||
backorder = False
|
||||
# Trigger the backorder process if we produce less than expected
|
||||
if float_compare(self.qty_producing, self.qty_remaining, precision_rounding=self.product_uom_id.rounding) == -1 and self.is_first_started_wo:
|
||||
if float_compare(self.qty_producing, self.qty_remaining,
|
||||
precision_rounding=self.product_uom_id.rounding) == -1 and self.is_first_started_wo:
|
||||
backorder = self.production_id._split_productions()[1:]
|
||||
for workorder in backorder.workorder_ids:
|
||||
if workorder.product_tracking == 'serial':
|
||||
@@ -423,7 +436,8 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
else:
|
||||
if self.operation_id:
|
||||
backorder = (self.production_id.procurement_group_id.mrp_production_ids - self.production_id).filtered(
|
||||
lambda p: p.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_id).state not in ('cancel', 'done')
|
||||
lambda p: p.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_id).state not in (
|
||||
'cancel', 'done')
|
||||
)[:1]
|
||||
else:
|
||||
index = list(self.production_id.workorder_ids).index(self)
|
||||
@@ -442,7 +456,8 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
wo.current_quality_check_id._update_component_quantity()
|
||||
if not self.env.context.get('no_start_next'):
|
||||
if self.operation_id:
|
||||
return backorder.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_id).open_tablet_view()
|
||||
return backorder.workorder_ids.filtered(
|
||||
lambda wo: wo.operation_id == self.operation_id).open_tablet_view()
|
||||
else:
|
||||
index = list(self.production_id.workorder_ids).index(self)
|
||||
return backorder.workorder_ids[index].open_tablet_view()
|
||||
@@ -466,7 +481,8 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
|
||||
def open_tablet_view(self):
|
||||
self.ensure_one()
|
||||
if not self.is_user_working and self.working_state != 'blocked' and self.state in ('ready', 'waiting', 'progress', 'pending'):
|
||||
if not self.is_user_working and self.working_state != 'blocked' and self.state in (
|
||||
'ready', 'waiting', 'progress', 'pending'):
|
||||
self.button_start()
|
||||
action = self.env["ir.actions.actions"]._for_xml_id("mrp_workorder.tablet_client_action")
|
||||
action['target'] = 'fullscreen'
|
||||
@@ -521,7 +537,8 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
data = {
|
||||
'mrp.workorder': self.read(self._get_fields_for_tablet(), load=False)[0],
|
||||
'quality.check': self.check_ids._get_fields_for_tablet(sorted_check_list),
|
||||
'operation': self.operation_id.read(self.operation_id._get_fields_for_tablet())[0] if self.operation_id else {},
|
||||
'operation': self.operation_id.read(self.operation_id._get_fields_for_tablet())[
|
||||
0] if self.operation_id else {},
|
||||
'working_state': self.workcenter_id.working_state,
|
||||
'views': {
|
||||
'workorder': self.env.ref('mrp_workorder.mrp_workorder_view_form_tablet').id,
|
||||
@@ -553,7 +570,8 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
|
||||
return {
|
||||
'duration': self.duration,
|
||||
'position': bisect_left(last30op, self.duration), # which position regarded other workorders ranked by duration
|
||||
'position': bisect_left(last30op, self.duration),
|
||||
# which position regarded other workorders ranked by duration
|
||||
'quality_score': score,
|
||||
'show_rainbow': show_rainbow,
|
||||
}
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
</field>
|
||||
</page>
|
||||
</page>
|
||||
<xpath expr="//sheet" position="after">
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="activity_ids"/>
|
||||
<field name="message_ids" options="{'post_refresh': 'recipients'}"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -67,9 +67,10 @@ class JdEclp(models.Model):
|
||||
"""
|
||||
判断是否为出库单
|
||||
"""
|
||||
if self.name:
|
||||
is_check_out = self.name.split('/')
|
||||
self.check_out = is_check_out[1]
|
||||
for record in self:
|
||||
if record.name:
|
||||
is_check_out = record.name.split('/')
|
||||
record.check_out = is_check_out[1]
|
||||
|
||||
@api.depends('carrier_tracking_ref')
|
||||
def query_bill_pdf(self):
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<field name='categ_id' class="custom_required" attrs="{'readonly': [('id', '!=', False)]}"/>
|
||||
<field name='is_bfm' invisible="1"/>
|
||||
<field name='categ_type' invisible="1"/>
|
||||
<field name='part_number' attrs="{'invisible': [('categ_type', '!=', '成品')]}"/>
|
||||
<field name='manual_quotation' attrs="{'invisible':[('upload_model_file', '=', [])]}"/>
|
||||
<field name="upload_model_file"
|
||||
widget="many2many_binary"
|
||||
|
||||
@@ -215,7 +215,7 @@ class Manufacturing_Connect(http.Controller):
|
||||
if workorder.state != 'progress':
|
||||
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '该工单未开始'}
|
||||
return json.JSONEncoder().encode(res)
|
||||
workorder.button_finish()
|
||||
workorder.write({'date_finished': datetime.now()})
|
||||
# workorder.process_state = '待解除装夹'
|
||||
# workorder.sudo().production_id.process_state = '待解除装夹'
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
import requests
|
||||
import logging
|
||||
import time
|
||||
from odoo import fields, models
|
||||
from odoo import fields, models, api
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class AgvSetting(models.Model):
|
||||
@@ -59,11 +60,17 @@ class AgvTaskRoute(models.Model):
|
||||
('F01', '搬运'), ], string='任务类型', default="F01")
|
||||
route_type = fields.Selection([
|
||||
('上产线', '上产线'), ('下产线', '下产线'), ('运送空料架', '运送空料架')], string='类型')
|
||||
start_site_id = fields.Many2one('sf.agv.site', '起点接驳站位置编号')
|
||||
end_site_id = fields.Many2one('sf.agv.site', '终点接驳站位置编号')
|
||||
start_site_id = fields.Many2one('sf.agv.site', '起点接驳站')
|
||||
end_site_id = fields.Many2one('sf.agv.site', '终点接驳站')
|
||||
destination_production_line_id = fields.Many2one('sf.production.line', '目的生产线')
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
@api.constrains('end_site_id')
|
||||
def _check_end_site_id(self):
|
||||
if self.end_site_id:
|
||||
if self.end_site_id == self.start_site_id:
|
||||
raise UserError("您选择的终点接驳站与起点接驳站重复,请重新选择")
|
||||
|
||||
|
||||
class Center_controlInterfaceLog(models.Model):
|
||||
_name = 'center_control.interface.log'
|
||||
|
||||
@@ -53,13 +53,13 @@ class MrpProduction(models.Model):
|
||||
active = fields.Boolean(string='已归档', default=True)
|
||||
programming_no = fields.Char('编程单号')
|
||||
work_state = fields.Char('业务状态')
|
||||
programming_state = fields.Char('编程状态')
|
||||
programming_state = fields.Char('编程状态', tracking=True)
|
||||
glb_file = fields.Binary("glb模型文件")
|
||||
production_line_id = fields.Many2one('sf.production.line', string='生产线')
|
||||
production_line_id = fields.Many2one('sf.production.line', string='生产线', tracking=True)
|
||||
plan_start_processing_time = fields.Datetime('计划开始加工时间')
|
||||
production_line_state = fields.Selection(
|
||||
[('待上产线', '待上产线'), ('已上产线', '已上产线'), ('已下产线', '已下产线')],
|
||||
string='上/下产线', default='待上产线')
|
||||
string='上/下产线', default='待上产线', tracking=True)
|
||||
# 工序状态
|
||||
# Todo 研究下用法
|
||||
process_state = fields.Selection([
|
||||
@@ -77,6 +77,7 @@ class MrpProduction(models.Model):
|
||||
part_drawing = fields.Binary('零件图纸')
|
||||
|
||||
manual_quotation = fields.Boolean('人工编程', default=False, readonly=True)
|
||||
rework_production = fields.Many2one('mrp.production', string='返工的制造订单')
|
||||
|
||||
@api.depends(
|
||||
'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state',
|
||||
@@ -154,8 +155,30 @@ class MrpProduction(models.Model):
|
||||
for production in self:
|
||||
production.maintenance_count = len(production.request_ids)
|
||||
|
||||
# 制造订单报废:编程单更新
|
||||
def updateCNC(self):
|
||||
try:
|
||||
res = {'production_no': self.name, 'programming_no': self.programming_no,
|
||||
'order_no': self.origin}
|
||||
logging.info('res=%s:' % res)
|
||||
configsettings = self.env['res.config.settings'].get_values()
|
||||
config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])
|
||||
url = '/api/intelligent_programming/update_intelligent_programmings'
|
||||
config_url = configsettings['sf_url'] + url
|
||||
res['token'] = configsettings['token']
|
||||
ret = requests.post(config_url, json={}, data=res, headers=config_header)
|
||||
ret = ret.json()
|
||||
logging.info('updateCNC-ret:%s' % ret)
|
||||
if ret['status'] == 1:
|
||||
self.write({'work_state': '已编程'})
|
||||
else:
|
||||
raise UserError(ret['message'])
|
||||
except Exception as e:
|
||||
logging.info('updateCNC error:%s' % e)
|
||||
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])])
|
||||
@@ -171,6 +194,8 @@ class MrpProduction(models.Model):
|
||||
'production_no': production_names,
|
||||
'machine_tool_code': '',
|
||||
'product_name': cnc.product_id.name,
|
||||
'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,
|
||||
@@ -268,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对应的生产订单名称列表
|
||||
@@ -311,11 +336,16 @@ 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': '已编程' if production_programming.programming_state == '已编程' else '编程中'})
|
||||
'programming_state': '编程中'})
|
||||
|
||||
# # 根据加工面板的面数及对应的工序模板生成工单
|
||||
i = 0
|
||||
processing_panel_len = len(production.product_id.model_processing_panel.split(','))
|
||||
@@ -527,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
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
Z10_axis = fields.Float(default=0)
|
||||
X_deviation_angle = fields.Integer(string="X轴偏差度", default=0)
|
||||
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], default='合格',
|
||||
string="检测结果")
|
||||
string="检测结果", tracking=True)
|
||||
cnc_ids = fields.One2many("sf.cnc.processing", 'workorder_id', string="CNC加工程序")
|
||||
cmm_ids = fields.One2many("sf.cmm.program", 'workorder_id', string="CMM程序")
|
||||
tray_code = fields.Char(string="托盘编码")
|
||||
@@ -133,7 +133,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
return action
|
||||
|
||||
supplier_id = fields.Many2one('res.partner', string='外协供应商')
|
||||
equipment_id = fields.Many2one('maintenance.equipment', string='加工设备')
|
||||
equipment_id = fields.Many2one('maintenance.equipment', string='加工设备', tracking=True)
|
||||
is_ok = fields.Boolean(string='是否合格')
|
||||
# 加工人
|
||||
processing_user_id = fields.Many2one('res.users', string='加工人')
|
||||
@@ -195,11 +195,16 @@ class ResMrpWorkOrder(models.Model):
|
||||
rfid_code_old = fields.Char('RFID码(已解除)')
|
||||
|
||||
production_line_id = fields.Many2one('sf.production.line', related='production_id.production_line_id',
|
||||
string='生产线', store=True)
|
||||
string='生产线', store=True, tracking=True)
|
||||
production_line_state = fields.Selection(related='production_id.production_line_state',
|
||||
string='上/下产线', store=True)
|
||||
string='上/下产线', store=True, tracking=True)
|
||||
detection_report = fields.Binary('检测报告', readonly=True)
|
||||
is_remanufacture = fields.Boolean(string='是否重新生成制造订单', default=True)
|
||||
is_remanufacture = fields.Boolean(string='重新生成制造订单', default=False)
|
||||
is_fetchcnc = fields.Boolean(string='重新获取NC程序', default=False)
|
||||
reason = fields.Selection(
|
||||
[("programming", "编程"), ("clamping", "返工"), ("cutter", "刀具"), ("operate computer", "操机"),
|
||||
("technology", "工艺"), ("customer redrawing", "客户改图"), ("other", "其他"), ], string="原因", tracking=True)
|
||||
detailed_reason = fields.Text('详细原因')
|
||||
|
||||
@api.onchange('rfid_code')
|
||||
def _onchange(self):
|
||||
@@ -672,14 +677,14 @@ class ResMrpWorkOrder(models.Model):
|
||||
"""
|
||||
重新生成制造订单或者重新生成工单
|
||||
"""
|
||||
if self.test_results == '报废':
|
||||
if self.test_results in ['返工', '报废']:
|
||||
values = self.env['mrp.production'].create_production1_values(self.production_id)
|
||||
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(
|
||||
self.production_id.company_id).create(
|
||||
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
|
||||
@@ -761,6 +766,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
|
||||
sale_order = self.env['sale.order'].sudo().search([('name', '=', productions.origin)])
|
||||
if sale_order:
|
||||
sale_order.mrp_production_ids |= productions
|
||||
# sale_order.write({'schedule_status': 'to schedule'})
|
||||
self.env['sf.production.plan'].sudo().with_company(self.production_id.company_id).create({
|
||||
'name': productions.name,
|
||||
@@ -772,13 +778,13 @@ class ResMrpWorkOrder(models.Model):
|
||||
'product_id': productions.product_id.id,
|
||||
'state': 'draft',
|
||||
})
|
||||
if self.test_results == '返工':
|
||||
productions = self.production_id
|
||||
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
|
||||
# self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
||||
productions._create_workorder2(self.processing_panel)
|
||||
else:
|
||||
self.results = '合格'
|
||||
# if self.test_results == '返工':
|
||||
# productions = self.production_id
|
||||
# # self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
|
||||
# # self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
||||
# productions._create_workorder2(self.processing_panel)
|
||||
# else:
|
||||
# self.results = '合格'
|
||||
|
||||
def json_workorder_str1(self, k, production, route):
|
||||
workorders_values_str = [0, '', {
|
||||
@@ -803,29 +809,28 @@ class ResMrpWorkOrder(models.Model):
|
||||
}]
|
||||
return workorders_values_str
|
||||
|
||||
@api.depends('production_availability', 'blocked_by_workorder_ids', 'blocked_by_workorder_ids.state')
|
||||
def _compute_state(self):
|
||||
super(ResMrpWorkOrder, self)._compute_state()
|
||||
for item in self:
|
||||
scrap_workorder = self.env['mrp.workorder'].search(
|
||||
[('production_id', '=', item.production_id.id), ('routing_type', '=', 'CNC加工'),
|
||||
('state', '=', 'done'), ('is_remanufacture', '=', True)])
|
||||
print(item.name)
|
||||
print(item.state)
|
||||
if item.name == 'CNC加工(返工)' and item.state not in ['ready', 'progress', 'done']:
|
||||
item.state = 'ready'
|
||||
if item.routing_type == '解除装夹':
|
||||
last_workorder = self.env['mrp.workorder'].search(
|
||||
[('production_id', '=', item.production_id.id), ('name', '=', 'CNC加工(返工)'),
|
||||
('state', '!=', 'done')])
|
||||
if item.state != 'pending':
|
||||
if last_workorder:
|
||||
item.state = 'pending'
|
||||
if scrap_workorder:
|
||||
item.state = 'cancel'
|
||||
elif item.routing_type == '表面工艺':
|
||||
if scrap_workorder:
|
||||
item.state = 'cancel'
|
||||
# @api.depends('production_availability', 'blocked_by_workorder_ids', 'blocked_by_workorder_ids.state')
|
||||
# def _compute_state(self):
|
||||
# super(ResMrpWorkOrder, self)._compute_state()
|
||||
# for item in self:
|
||||
# print(item.name)
|
||||
# print(item.state)
|
||||
# print(item.is_remanufacture)
|
||||
# scrap_workorder = self.env['mrp.workorder'].search(
|
||||
# [('production_id', '=', item.production_id.id), ('routing_type', '=', 'CNC加工'),
|
||||
# ('state', '=', 'done'), ('test_results', 'in', ['返工', '报废'])])
|
||||
# print(scrap_workorder)
|
||||
# # if item.routing_type == 'CNC加工' and item.state in ['done'] and item.test_results in ['返工', '报废']:
|
||||
# if item.routing_type == '解除装夹':
|
||||
# if scrap_workorder and item.state not in ['cancel']:
|
||||
# item.state = 'cancel'
|
||||
# elif item.routing_type == '表面工艺':
|
||||
# if scrap_workorder:
|
||||
# stock_move = self.env['stock.move'].search(
|
||||
# [('origin', '=', item.production_id.name)])
|
||||
# stock_move.write({'state': 'cancel'})
|
||||
# item.picking_ids.write({'state': 'cancel'})
|
||||
# item.state = 'cancel'
|
||||
|
||||
# 重写工单开始按钮方法
|
||||
def button_start(self):
|
||||
@@ -982,6 +987,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
raise UserError(
|
||||
'请先在产品中配置表面工艺为%s相关的外协服务产品' % item.surface_technics_parameters_id.name)
|
||||
tem_date_planned_finished = record.date_planned_finished
|
||||
tem_date_finished = record.date_finished
|
||||
logging.info('routing_type:%s' % record.routing_type)
|
||||
super().button_finish()
|
||||
logging.info('date_planned_finished:%s' % record.date_planned_finished)
|
||||
@@ -990,8 +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.recreateManufacturingOrWorkerOrder()
|
||||
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':
|
||||
@@ -1132,14 +1145,14 @@ class CNCprocessing(models.Model):
|
||||
# 根据程序名和加工面匹配到ftp里对应的Nc程序名,可优化为根据cnc_processing.program_path进行匹配
|
||||
def get_cnc_processing_file(self, serverdir, cnc_processing, program_path):
|
||||
logging.info('serverdir:%s' % serverdir)
|
||||
logging.info('cnc_processing:%s' % cnc_processing)
|
||||
for root, dirs, files in os.walk(serverdir):
|
||||
for f in files:
|
||||
logging.info('splitext(f):%s' % os.path.splitext(f)[1])
|
||||
if os.path.splitext(f)[1] == ".pdf":
|
||||
full_path = os.path.join(serverdir, root, f)
|
||||
if full_path is not False:
|
||||
if not cnc_processing.workorder_id.cnc_worksheet:
|
||||
cnc_processing.workorder_id.cnc_worksheet = base64.b64encode(
|
||||
open(full_path, 'rb').read())
|
||||
cnc_processing.workorder_id.cnc_worksheet = base64.b64encode(
|
||||
open(full_path, 'rb').read())
|
||||
else:
|
||||
if f in program_path:
|
||||
# if cnc_processing.program_name == f.split('.')[0]:
|
||||
@@ -1305,17 +1318,18 @@ class SfWorkOrderBarcodes(models.Model):
|
||||
|
||||
class WorkPieceDelivery(models.Model):
|
||||
_name = "sf.workpiece.delivery"
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_description = '工件配送'
|
||||
|
||||
name = fields.Char('单据编号')
|
||||
name = fields.Char('单据编码')
|
||||
workorder_id = fields.Many2one('mrp.workorder', string='工单', readonly=True)
|
||||
workorder_state = fields.Selection(related='workorder_id.state', string='工单状态')
|
||||
rfid_code = fields.Char(related='workorder_id.rfid_code', string='rfid码', store=True)
|
||||
production_id = fields.Many2one('mrp.production', string='制造订单号', readonly=True)
|
||||
production_line_id = fields.Many2one('sf.production.line', string='目的生产线')
|
||||
production_line_id = fields.Many2one('sf.production.line', string='目的生产线', tracking=True)
|
||||
plan_start_processing_time = fields.Datetime('计划开始加工时间', readonly=True)
|
||||
|
||||
route_id = fields.Many2one('sf.agv.task.route', '任务路线')
|
||||
route_id = fields.Many2one('sf.agv.task.route', '任务路线', tracking=True)
|
||||
feeder_station_start_id = fields.Many2one('sf.agv.site', '起点接驳站')
|
||||
feeder_station_destination_id = fields.Many2one('sf.agv.site', '目的接驳站')
|
||||
task_delivery_time = fields.Datetime('任务下发时间')
|
||||
@@ -1324,26 +1338,41 @@ class WorkPieceDelivery(models.Model):
|
||||
[('上产线', '上产线'), ('下产线', '下产线'), ('运送空料架', '运送空料架')], string='类型')
|
||||
delivery_duration = fields.Float('配送时长', compute='_compute_delivery_duration')
|
||||
status = fields.Selection(
|
||||
[('待下发', '待下发'), ('待配送', '待配送'), ('已配送', '已配送')], string='状态', default='待下发')
|
||||
is_cnc_program_down = fields.Boolean('程序是否下发', default=False)
|
||||
[('待下发', '待下发'), ('待配送', '待配送'), ('已配送', '已配送')], string='状态', default='待下发',
|
||||
tracking=True)
|
||||
is_cnc_program_down = fields.Boolean('程序是否下发', default=False, tracking=True)
|
||||
is_manual_work = fields.Boolean('人工操作', default=False)
|
||||
active = fields.Boolean(string="有效", default=True)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('name', '/') == '/' or vals.get('name', '/') is False:
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('sf.workpiece.delivery') or '/'
|
||||
else:
|
||||
if vals['route_id'] and vals.get('type') is None:
|
||||
vals['type'] = '运送空料架'
|
||||
else:
|
||||
if vals.get('name', '/') == '/' or vals.get('name', '/') is False:
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('sf.workpiece.delivery') or '/'
|
||||
obj = super(WorkPieceDelivery, self).create(vals)
|
||||
if obj.type == '运送空料架':
|
||||
if obj.name is False:
|
||||
obj.name = "运送空料架路线:%s-%s" % (
|
||||
obj.feeder_station_start_id.name, obj.feeder_station_destination_id.name)
|
||||
return obj
|
||||
|
||||
@api.constrains('name')
|
||||
def _check_name(self):
|
||||
@api.constrains('route_id')
|
||||
def _check_route_id(self):
|
||||
if self.type == '运送空料架':
|
||||
wd = self.sudo().search([('name', '=', self.name), ('id', '!=', self.id)])
|
||||
if wd:
|
||||
raise UserError("该名称已存在")
|
||||
if self.route_id and self.name is False:
|
||||
route = self.sudo().search(
|
||||
[('route_id', '=', self.route_id.id), ('id', '!=', self.id), ('name', 'ilike', '运送空料架路线')])
|
||||
if route:
|
||||
raise UserError("该任务路线已存在,请重新选择")
|
||||
|
||||
# @api.constrains('name')
|
||||
# def _check_name(self):
|
||||
# if self.type == '运送空料架':
|
||||
# wd = self.sudo().search([('name', '=', self.name), ('id', '!=', self.id)])
|
||||
# if wd:
|
||||
# raise UserError("该名称已存在")
|
||||
|
||||
def action_delivery_history(self):
|
||||
return {
|
||||
|
||||
@@ -530,6 +530,7 @@ class ResProductMo(models.Model):
|
||||
|
||||
# bfm下单
|
||||
manual_quotation = fields.Boolean('人工编程', default=False, readonly=True)
|
||||
part_number = fields.Char(string='零件图号', readonly=True)
|
||||
|
||||
@api.constrains('tool_length')
|
||||
def _check_tool_length_size(self):
|
||||
@@ -626,6 +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['part_number'] or '',
|
||||
'active': True,
|
||||
}
|
||||
copy_product_id.sudo().write(vals)
|
||||
|
||||
@@ -207,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 \
|
||||
(
|
||||
@@ -631,8 +631,8 @@ class ReStockMove(models.Model):
|
||||
'reserved_uom_qty': 1.0,
|
||||
'lot_id': purchase.picking_ids.move_line_ids.lot_id.id,
|
||||
'company_id': self.company_id.id,
|
||||
'workorder_id': '' if not sorted_workorders else sorted_workorders.id,
|
||||
'production_id': '' if not sorted_workorders else sorted_workorders.production_id.id,
|
||||
# 'workorder_id': '' if not sorted_workorders else sorted_workorders.id,
|
||||
# 'production_id': '' if not sorted_workorders else sorted_workorders.production_id.id,
|
||||
'state': 'assigned',
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<field name="model">sf.agv.site</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="bottom">
|
||||
<field name="name" required="1"/>
|
||||
<field name="owning_region" required="1"/>
|
||||
<field name="state" required="1"/>
|
||||
<field name="name" required="1" attrs="{'readonly': [('id', '!=', False)]}"/>
|
||||
<field name="owning_region" required="1" attrs="{'readonly': [('id', '!=', False)]}"/>
|
||||
<field name="state" required="1" attrs="{'readonly': [('id', '!=', False)]}"/>
|
||||
<field name="divide_the_work" required="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
@@ -34,12 +34,14 @@
|
||||
<field name="model">sf.agv.task.route</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="bottom">
|
||||
<field name="name" required="1"/>
|
||||
<field name="name" required="1" attrs="{'readonly': [('id', '!=', False)]}"/>
|
||||
<field name="type" readonly="1" string="任务类型"/>
|
||||
<field name="route_type" string="类型" required="1"/>
|
||||
<field name="start_site_id" required="1" options="{'no_create': True}" string="起点接驳站"/>
|
||||
<field name="route_type" string="类型" required="1" attrs="{'readonly': [('id', '!=', False)]}"/>
|
||||
<field name="start_site_id" required="1" options="{'no_create': True}" string="起点接驳站"
|
||||
attrs="{'readonly': [('id', '!=', False)]}"/>
|
||||
<field name="end_site_id" required="1" options="{'no_create': True}" string="终点接驳站"/>
|
||||
<field name="destination_production_line_id" required="1" options="{'no_create': True}"/>
|
||||
<field name="destination_production_line_id" required="1" options="{'no_create': True}"
|
||||
attrs="{'readonly': [('id', '!=', False)]}"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -73,7 +75,8 @@
|
||||
<field name="model">center_control.interface.log</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Logs">
|
||||
<field name="name"/>
|
||||
<field name="name" filter_domain="[('name','ilike', self)]"/>
|
||||
<field name="content" filter_domain="[('content','ilike', self)]"/>
|
||||
<group expand="0" string="分组">
|
||||
<field name="interface_call_date"/>
|
||||
</group>
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
<xpath expr="//field[@name='user_id']" position="after">
|
||||
<field name="production_line_id" readonly="1"/>
|
||||
<field name="production_line_state" readonly="1"/>
|
||||
<field name="part_number"/>
|
||||
<field name="part_number" string="成品的零件图号"/>
|
||||
<field name="part_drawing"/>
|
||||
</xpath>
|
||||
<xpath expr="//header//button[@name='action_cancel']" position="replace">
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
|
||||
<field name="functional_fixture_type_id"
|
||||
attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
|
||||
<field name="rfid_code" force_save="1" readonly="1" cache="True"
|
||||
<field name="rfid_code" cache="True"
|
||||
attrs="{'invisible': [('rfid_code_old', '!=', False)]}"/>
|
||||
<field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>
|
||||
</group>
|
||||
@@ -478,6 +478,11 @@
|
||||
<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="detection_report" attrs='{"invisible":[("results","!=",False)]}'
|
||||
widget="pdf_viewer"/>
|
||||
@@ -573,7 +578,7 @@
|
||||
<label for="material_height" string="高"/>
|
||||
<field name="material_height" class="o_address_zip"/>
|
||||
</div>
|
||||
<field name="part_number"/>
|
||||
<field name="part_number" string="成品的零件图号"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
@@ -604,7 +609,7 @@
|
||||
<field name="name">工件配送</field>
|
||||
<field name="model">sf.workpiece.delivery</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="工件配送" editable="bottom" class="center" create="0" delete="0">
|
||||
<tree string="工件配送" class="center" create="0" delete="0">
|
||||
<header>
|
||||
<button name="button_delivery" type="object" string="配送" class="oe_highlight"/>
|
||||
</header>
|
||||
@@ -612,6 +617,7 @@
|
||||
decoration-success="status == '已配送'"
|
||||
decoration-warning="status == '待下发'"
|
||||
decoration-danger="status == '待配送'"/>
|
||||
<field name="name"/>
|
||||
<field name="production_id"/>
|
||||
<field name="type" readonly="1"/>
|
||||
<field name="production_line_id" options="{'no_create': True}" readonly="1"/>
|
||||
@@ -628,13 +634,58 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="sf_workpiece_delivery_form" model="ir.ui.view">
|
||||
<field name="name">工件配送</field>
|
||||
<field name="model">sf.workpiece.delivery</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="工件配送" create="0" delete="0">
|
||||
<header>
|
||||
<field name="status" widget="statusbar"/>
|
||||
<button name="button_delivery" type="object" string="配送" class="oe_highlight"
|
||||
attrs="{'invisible': [('status', '!=', '待下发')]}"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<field name="name" readonly="1"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group string="基本信息">
|
||||
<field name="production_id"/>
|
||||
<field name="type" readonly="1"/>
|
||||
<field name="production_line_id" options="{'no_create': True}" readonly="1"/>
|
||||
<field name="is_cnc_program_down" readonly="1"/>
|
||||
<!-- <field name="rfid_code"/>-->
|
||||
</group>
|
||||
<group string="配送信息">
|
||||
<field name="route_id" options="{'no_create': True}"
|
||||
domain="[('route_type','in',['上产线','下产线'])]"/>
|
||||
<field name="feeder_station_start_id" readonly="1" force_save="1"/>
|
||||
<field name="feeder_station_destination_id" readonly="1" force_save="1"/>
|
||||
<field name="task_delivery_time" readonly="1"/>
|
||||
<field name="task_completion_time" readonly="1"/>
|
||||
<field name="delivery_duration" widget="float_time"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="activity_ids"/>
|
||||
<field name="message_ids" options="{'post_refresh': 'recipients'}"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="sf_workpiece_delivery_search" model="ir.ui.view">
|
||||
<field name="name">工件配送</field>
|
||||
<field name="model">sf.workpiece.delivery</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="工件配送">
|
||||
<filter string="上产线" name="on_up" domain="[('type', '=', '上产线')]"/>
|
||||
<filter string="下产线" name="on_down" domain="[('type', '=', '下产线' )]"/>
|
||||
<filter name="filter_to_be_issued" string="待下发" domain="[('status', 'in', ['待下发'])]"/>
|
||||
<filter name="filter_waiting_delivery" string="待配送" domain="[('status', 'in', ['待配送'])]"/>
|
||||
<filter name="filter_delivered" string="已配送" domain="[('status', 'in', ['已配送'])]"/>
|
||||
<field name="rfid_code"/>
|
||||
<field name="production_id"/>
|
||||
<field name="feeder_station_start_id"/>
|
||||
@@ -656,8 +707,10 @@
|
||||
<field name="name">工件配送</field>
|
||||
<field name="res_model">sf.workpiece.delivery</field>
|
||||
<field name="search_view_id" ref="sf_workpiece_delivery_search"/>
|
||||
<field name="context">{'search_default_on_up':1}</field>
|
||||
<field name="view_mode">tree,search</field>
|
||||
<field name="context">{'search_default_filter_to_be_issued': 1,
|
||||
'search_default_filter_waiting_delivery': 1}
|
||||
</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">
|
||||
[('type','in',['上产线','下产线']),('workorder_state','=','done'),('is_manual_work','=',false)]
|
||||
</field>
|
||||
@@ -670,23 +723,39 @@
|
||||
<field name="model">sf.workpiece.delivery</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="工件配送" editable="bottom" class="center" delete="0" create="1">
|
||||
<header>
|
||||
<button name="button_delivery" type="object" string="配送" class="oe_highlight"/>
|
||||
</header>
|
||||
<field name="name" string="路线名称" attrs="{'readonly': [('id', '!=', False)]}"
|
||||
placeholder="例如:运送空料架路线:G01-A01" required="1" force_save="1"/>
|
||||
<!-- <header>-->
|
||||
<!-- <button name="button_delivery" type="object" string="配送" class="oe_highlight"/>-->
|
||||
<!-- </header>-->
|
||||
<!-- <field name="name" string="路线名称" attrs="{'readonly': [('id', '!=', False)]}"-->
|
||||
<!-- placeholder="例如:运送空料架路线:G01-A01" required="1" force_save="1"/>-->
|
||||
<field name="route_id" options="{'no_create': True}" required="1"
|
||||
attrs="{'readonly': [('id', '!=', False)]}" domain="[('route_type', '=', '运送空料架')]"
|
||||
force_save="1"/>
|
||||
<field name="feeder_station_start_id" readonly="1" force_save="1"/>
|
||||
<!-- <field name="type" readonly="1"/>-->
|
||||
<field name="feeder_station_destination_id" readonly="1" force_save="1"/>
|
||||
<button name="button_delivery" type="object" string="配送" class="oe_highlight"/>
|
||||
<button name="action_delivery_history" type="object" class="btn btn-link text-info" icon="fa-history"
|
||||
string="历史"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- <record id="sf_workpiece_delivery_empty_racks_kanban" model="ir.ui.view">-->
|
||||
<!-- <field name="name">sf.workpiece.delivery.view.kanban</field>-->
|
||||
<!-- <field name="model">sf.workpiece.delivery</field>-->
|
||||
<!-- <field name="arch" type="xml">-->
|
||||
<!-- <kanban>-->
|
||||
<!-- <field name="route_id"/>-->
|
||||
<!-- <field name="feeder_station_start_id"/>-->
|
||||
<!-- <field name="feeder_station_destination_id"/>-->
|
||||
<!--<!– <button name="button_delivery" type="object" string="配送" class="oe_highlight"/>–>-->
|
||||
<!--<!– <button name="action_delivery_history" type="object" class="btn btn-link text-info" icon="fa-history"–>-->
|
||||
<!--<!– string="历史"/>–>-->
|
||||
<!-- </kanban>-->
|
||||
<!-- </field>-->
|
||||
<!-- </record>-->
|
||||
|
||||
<record id="sf_workpiece_delivery_empty_racks_tree" model="ir.ui.view">
|
||||
<field name="name">空料架配送</field>
|
||||
<field name="model">sf.workpiece.delivery</field>
|
||||
@@ -709,6 +778,7 @@
|
||||
<field name="model">sf.workpiece.delivery</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="运送空料架">
|
||||
<filter name="filter_active" string="已归档" domain="[('active', '=', False)]"/>
|
||||
<field name="route_id"/>
|
||||
<field name="feeder_station_start_id"/>
|
||||
<field name="feeder_station_destination_id"/>
|
||||
|
||||
@@ -24,12 +24,22 @@ class Sf_Mrs_Connect(http.Controller):
|
||||
ret = json.loads(datas)
|
||||
ret = json.loads(ret['result'])
|
||||
logging.info('下发编程单:%s' % ret)
|
||||
is_delete_file = False
|
||||
# 查询状态为进行中且类型为获取CNC加工程序的工单
|
||||
cnc_production = request.env['mrp.production'].with_user(
|
||||
request.env.ref("base.user_admin")).search([('name', '=', ret['production_order_no'].split(',')[0])])
|
||||
cnc_program = request.env['mrp.production'].with_user(
|
||||
request.env.ref("base.user_admin")).search(
|
||||
[('programming_no', '=', cnc_production.programming_no), ('id', '!=', cnc_production.id)])
|
||||
if cnc_production.workorder_ids.filtered(lambda a: a.routing_type == 'CNC加工').cnc_ids:
|
||||
is_delete_file = True
|
||||
cnc_production.workorder_ids.filtered(
|
||||
lambda a1: a1.routing_type == 'CNC加工').cnc_ids.sudo().unlink()
|
||||
request.env['sf.cam.work.order.program.knife.plan'].sudo().unlink_cam_plan(cnc_production)
|
||||
if cnc_program.workorder_ids.filtered(lambda c: c.routing_type == 'CNC加工').cnc_ids:
|
||||
cnc_program.workorder_ids.filtered(
|
||||
lambda c1: c1.routing_type == 'CNC加工').cnc_ids.sudo().unlink()
|
||||
request.env['sf.cam.work.order.program.knife.plan'].sudo().unlink_cam_plan(cnc_program)
|
||||
# cnc_program = request.env['mrp.production'].with_user(
|
||||
# request.env.ref("base.user_admin")).search([('programming_no', '=', cnc_production.programming_no)])
|
||||
logging.info('制造订单号:%s' % cnc_production.name)
|
||||
@@ -37,6 +47,13 @@ class Sf_Mrs_Connect(http.Controller):
|
||||
# if ret['glb_file']:
|
||||
# cnc_production.glb_file = base64.b64encode(ret['glb_file'])
|
||||
# 拉取所有加工面的程序文件
|
||||
if is_delete_file is True:
|
||||
program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', 'R')
|
||||
files_r = os.listdir(program_path_tmp_r)
|
||||
if files_r:
|
||||
for file_name in files_r:
|
||||
file_path = os.path.join(program_path_tmp_r, file_name)
|
||||
os.remove(file_path)
|
||||
for r in ret['processing_panel']:
|
||||
download_state = request.env['sf.cnc.processing'].with_user(
|
||||
request.env.ref("base.user_admin")).download_file_tmp(
|
||||
@@ -64,15 +81,17 @@ class Sf_Mrs_Connect(http.Controller):
|
||||
if cnc_processing:
|
||||
cnc_processing_arr.append(cnc_processing._json_cnc_processing(cnc_processing))
|
||||
if (cnc_program and cnc_processing_arr) or (not cnc_program and cnc_processing_arr):
|
||||
logging.info('cnc_processing_arr:%s' % cnc_processing_arr)
|
||||
cnc_production.workorder_ids.filtered(lambda g: g.routing_type == '装夹预调').write(
|
||||
{'processing_drawing': cnc_production.workorder_ids.filtered(
|
||||
lambda g1: g1.routing_type == 'CNC加工').cnc_worksheet})
|
||||
if cnc_program and cnc_processing_arr:
|
||||
cnc_program.write({'programming_state': '已编程', 'work_state': '已编程'})
|
||||
cnc_program.workorder_ids.filtered(lambda b1: b1.routing_type == '装夹预调').write(
|
||||
cnc_program.workorder_ids.filtered(lambda d: d.routing_type == '装夹预调').write(
|
||||
{'processing_drawing': cnc_production.workorder_ids.filtered(
|
||||
lambda b1: b1.routing_type == 'CNC加工').cnc_worksheet})
|
||||
lambda d1: d1.routing_type == 'CNC加工').cnc_worksheet})
|
||||
cnc_program.workorder_ids.filtered(lambda b: b.routing_type == 'CNC加工').write(
|
||||
{'cnc_ids': cnc_processing_arr, 'cnc_worksheet': cnc_production.workorder_ids.filtered(
|
||||
lambda b: b.routing_type == 'CNC加工').cnc_worksheet})
|
||||
lambda b1: b1.routing_type == 'CNC加工').cnc_worksheet})
|
||||
cnc_program |= cnc_production
|
||||
if not cnc_program and cnc_processing_arr:
|
||||
cnc_program = cnc_production
|
||||
|
||||
@@ -46,6 +46,8 @@ class FtpController():
|
||||
os.makedirs(serverdir)
|
||||
try:
|
||||
logging.info("进入FTP目录 ")
|
||||
self.ftp.pwd()
|
||||
logging.info('当前目录:%s' % self.ftp.pwd())
|
||||
logging.info('目录:%s' % target_dir)
|
||||
target_dir1 = target_dir.split('/')
|
||||
logging.info('目录1:%s' % target_dir1[1])
|
||||
|
||||
@@ -135,12 +135,13 @@
|
||||
<!-- <field name="delivery_quantity"/> -->
|
||||
<!-- <field name="delivery_date"/> -->
|
||||
<!-- </group> -->
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_ids"/>
|
||||
</div>
|
||||
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_ids"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -19,6 +19,7 @@ from . import parser_and_calculate_work_time as pc
|
||||
|
||||
class QuickEasyOrder(models.Model):
|
||||
_name = 'quick.easy.order'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_description = '简易下单'
|
||||
_order = 'id desc'
|
||||
|
||||
@@ -35,13 +36,14 @@ class QuickEasyOrder(models.Model):
|
||||
('0.03', '±0.03mm'),
|
||||
('0.02', '±0.02mm'),
|
||||
('0.01', '±0.01mm')], string='加工精度', default='0.10')
|
||||
material_id = fields.Many2one('sf.production.materials', '材料')
|
||||
material_model_id = fields.Many2one('sf.materials.model', '型号')
|
||||
material_id = fields.Many2one('sf.production.materials', '材料', tracking=True)
|
||||
material_model_id = fields.Many2one('sf.materials.model', '型号', tracking=True)
|
||||
# process_id = fields.Many2one('sf.production.process', string='表面工艺')
|
||||
parameter_ids = fields.Many2many('sf.production.process.parameter', 'process_item_order_rel', string='可选参数')
|
||||
quantity = fields.Integer('数量', default=1)
|
||||
unit_price = fields.Float('单价')
|
||||
price = fields.Float('总价')
|
||||
parameter_ids = fields.Many2many('sf.production.process.parameter', 'process_item_order_rel', string='可选参数',
|
||||
tracking=True)
|
||||
quantity = fields.Integer('数量', default=1, tracking=True)
|
||||
unit_price = fields.Float('单价', tracking=True)
|
||||
price = fields.Float('总价', tracking=True)
|
||||
model_file = fields.Binary('glb模型文件')
|
||||
upload_model_file = fields.Many2many('ir.attachment', 'upload_qf_model_file_attachment_ref', string='上传模型文件')
|
||||
delivery_time = fields.Date('交货日期')
|
||||
@@ -49,10 +51,10 @@ class QuickEasyOrder(models.Model):
|
||||
state = fields.Selection([('草稿', '草稿'), ('待派单', '待派单'),
|
||||
('待接单', '待接单'), ('加工中', '加工中'),
|
||||
('物流中', '物流中'), ('已交付', '已交付')], string='订单状态', default='草稿',
|
||||
readonly=True)
|
||||
readonly=True, tracking=True)
|
||||
model_color_state = fields.Selection([
|
||||
('success', '成功'),
|
||||
('fail', '失败')], string='模型上色状态')
|
||||
('fail', '失败')], string='模型上色状态', tracking=True)
|
||||
processing_time = fields.Integer('加工时长(min)')
|
||||
sale_order_id = fields.Many2one('sale.order', '销售订单号')
|
||||
|
||||
@@ -94,8 +96,7 @@ class QuickEasyOrder(models.Model):
|
||||
obj.state = '待接单'
|
||||
return obj
|
||||
|
||||
|
||||
def model_analyze(self,model_attachment):
|
||||
def model_analyze(self, model_attachment):
|
||||
"""
|
||||
step模型解析,上传模型时转为web可显示的格式
|
||||
:return:
|
||||
|
||||
@@ -16,6 +16,7 @@ from odoo.exceptions import ValidationError, UserError
|
||||
|
||||
class QuickEasyOrder(models.Model):
|
||||
_name = 'quick.easy.order'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_description = '简易下单'
|
||||
_order = 'id desc'
|
||||
|
||||
@@ -32,13 +33,15 @@ class QuickEasyOrder(models.Model):
|
||||
('0.03', '±0.03mm'),
|
||||
('0.02', '±0.02mm'),
|
||||
('0.01', '±0.01mm')], string='加工精度', default='0.10')
|
||||
material_id = fields.Many2one('sf.production.materials', '材料')
|
||||
material_model_id = fields.Many2one('sf.materials.model', '型号', domain="[('materials_id', '=', material_id)]")
|
||||
material_id = fields.Many2one('sf.production.materials', '材料', tracking=True)
|
||||
material_model_id = fields.Many2one('sf.materials.model', '型号', domain="[('materials_id', '=', material_id)]",
|
||||
tracking=True)
|
||||
# process_id = fields.Many2one('sf.production.process', string='表面工艺')
|
||||
parameter_ids = fields.Many2many('sf.production.process.parameter', 'process_item_order_rel', string='可选参数')
|
||||
quantity = fields.Integer('数量', default=1)
|
||||
unit_price = fields.Float('单价')
|
||||
price = fields.Float('总价')
|
||||
parameter_ids = fields.Many2many('sf.production.process.parameter', 'process_item_order_rel', string='可选参数',
|
||||
tracking=True)
|
||||
quantity = fields.Integer('数量', default=1, tracking=True)
|
||||
unit_price = fields.Float('单价', tracking=True)
|
||||
price = fields.Float('总价', tracking=True)
|
||||
model_file = fields.Binary('glb模型文件')
|
||||
upload_model_file = fields.Many2many('ir.attachment', 'upload_qf_model_file_attachment_ref', string='上传模型文件')
|
||||
delivery_time = fields.Date('交货日期')
|
||||
@@ -46,10 +49,10 @@ class QuickEasyOrder(models.Model):
|
||||
state = fields.Selection([('草稿', '草稿'), ('待派单', '待派单'),
|
||||
('待接单', '待接单'), ('加工中', '加工中'),
|
||||
('物流中', '物流中'), ('已交付', '已交付')], string='订单状态', default='草稿',
|
||||
readonly=True)
|
||||
readonly=True, tracking=True)
|
||||
model_color_state = fields.Selection([
|
||||
('success', '成功'),
|
||||
('fail', '失败')], string='模型上色状态')
|
||||
('fail', '失败')], string='模型上色状态', tracking=True)
|
||||
processing_time = fields.Integer('加工时长(min)')
|
||||
sale_order_id = fields.Many2one('sale.order', '销售订单号')
|
||||
|
||||
|
||||
@@ -84,6 +84,11 @@
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="activity_ids"/>
|
||||
<field name="message_ids" options="{'post_refresh': 'recipients'}"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -8,6 +8,35 @@ from odoo.http import request
|
||||
|
||||
class Manufacturing_Connect(http.Controller):
|
||||
|
||||
@http.route('/AutoDeviceApi/ToolGroup', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
|
||||
cors="*")
|
||||
def get_functional_tool_groups_Info(self, **kw):
|
||||
"""
|
||||
刀具组接口
|
||||
:param kw:
|
||||
:return:
|
||||
"""
|
||||
logging.info('get_functional_tool_groups_Info:%s' % kw)
|
||||
try:
|
||||
datas = request.httprequest.data
|
||||
ret = json.loads(datas)
|
||||
# ret = json.loads(ret['result'])
|
||||
logging.info('DeviceId:%s' % ret)
|
||||
functional_tools = request.env['sf.tool.inventory'].sudo().search([])
|
||||
|
||||
res = {'Succeed': True, 'Datas': []}
|
||||
if functional_tools:
|
||||
for item in functional_tools:
|
||||
res['Datas'].append({
|
||||
'GroupName': item.tool_groups_id.name,
|
||||
'ToolId': item.functional_cutting_tool_model_id.name,
|
||||
'ToolName': item.name
|
||||
})
|
||||
except Exception as e:
|
||||
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
|
||||
logging.info('get_functional_tool_groups_Info error:%s' % e)
|
||||
return json.JSONEncoder().encode(res)
|
||||
|
||||
@http.route('/AutoDeviceApi/ToolInventory', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
|
||||
cors="*")
|
||||
def get_functional_tool_inventory_Info(self, **kw):
|
||||
@@ -97,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)
|
||||
@@ -311,41 +311,53 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
|
||||
'applicant': None,
|
||||
'sf_functional_tool_assembly_id': None})
|
||||
|
||||
def create_cam_work_plan(self, cnc_processing):
|
||||
def create_cam_work_plan(self, cnc_processing_ids):
|
||||
"""
|
||||
根据传入的工单信息,查询是否有需要的功能刀具,如果没有则生成CAM工单程序用刀计划
|
||||
"""
|
||||
status = False
|
||||
if cnc_processing.cutting_tool_name:
|
||||
functional_tools = self.env['sf.real.time.distribution.of.functional.tools'].sudo().search(
|
||||
[('name', '=', cnc_processing.cutting_tool_name)])
|
||||
if functional_tools:
|
||||
for functional_tool in functional_tools:
|
||||
if functional_tool.on_tool_stock_num == 0:
|
||||
if functional_tool.tool_stock_num == 0 and functional_tool.side_shelf_num == 0:
|
||||
status = True
|
||||
else:
|
||||
status = True
|
||||
if status:
|
||||
knife_plan = self.env['sf.cam.work.order.program.knife.plan'].sudo().create({
|
||||
'name': cnc_processing.workorder_id.production_id.name,
|
||||
'cam_procedure_code': cnc_processing.program_name,
|
||||
'filename': cnc_processing.cnc_id.name,
|
||||
'functional_tool_name': cnc_processing.cutting_tool_name,
|
||||
'cam_cutter_spacing_code': cnc_processing.cutting_tool_no,
|
||||
'process_type': cnc_processing.processing_type,
|
||||
'margin_x_y': float(cnc_processing.margin_x_y),
|
||||
'margin_z': float(cnc_processing.margin_z),
|
||||
'finish_depth': float(cnc_processing.depth_of_processing_z),
|
||||
'extension_length': float(cnc_processing.cutting_tool_extension_length),
|
||||
'shank_model': cnc_processing.cutting_tool_handle_type,
|
||||
'estimated_processing_time': cnc_processing.estimated_processing_time,
|
||||
})
|
||||
logging.info('CAM工单程序用刀计划创建成功!!!')
|
||||
# 创建装刀请求
|
||||
knife_plan.apply_for_tooling()
|
||||
else:
|
||||
logging.info('功能刀具【%s】满足CNC用刀需求!!!' % cnc_processing.cutting_tool_name)
|
||||
for cnc_processing in cnc_processing_ids:
|
||||
status = False
|
||||
if cnc_processing.cutting_tool_name:
|
||||
functional_tools = self.env['sf.real.time.distribution.of.functional.tools'].sudo().search(
|
||||
[('name', '=', cnc_processing.cutting_tool_name)])
|
||||
if functional_tools:
|
||||
for functional_tool in functional_tools:
|
||||
if functional_tool.on_tool_stock_num == 0:
|
||||
if functional_tool.tool_stock_num == 0 and functional_tool.side_shelf_num == 0:
|
||||
status = True
|
||||
else:
|
||||
status = True
|
||||
if status:
|
||||
knife_plan = self.env['sf.cam.work.order.program.knife.plan'].sudo().create({
|
||||
'name': cnc_processing.workorder_id.production_id.name,
|
||||
'cam_procedure_code': cnc_processing.program_name,
|
||||
'filename': cnc_processing.cnc_id.name,
|
||||
'functional_tool_name': cnc_processing.cutting_tool_name,
|
||||
'cam_cutter_spacing_code': cnc_processing.cutting_tool_no,
|
||||
'process_type': cnc_processing.processing_type,
|
||||
'margin_x_y': float(cnc_processing.margin_x_y),
|
||||
'margin_z': float(cnc_processing.margin_z),
|
||||
'finish_depth': float(cnc_processing.depth_of_processing_z),
|
||||
'extension_length': float(cnc_processing.cutting_tool_extension_length),
|
||||
'shank_model': cnc_processing.cutting_tool_handle_type,
|
||||
'estimated_processing_time': cnc_processing.estimated_processing_time,
|
||||
})
|
||||
logging.info('CAM工单程序用刀计划创建成功!!!')
|
||||
# 创建装刀请求
|
||||
knife_plan.apply_for_tooling()
|
||||
else:
|
||||
logging.info('功能刀具【%s】满足CNC用刀需求!!!' % cnc_processing.cutting_tool_name)
|
||||
|
||||
def unlink_cam_plan(self, production):
|
||||
for item in production:
|
||||
cam_plan_ids = self.env['sf.cam.work.order.program.knife.plan'].search([('name', '=', item.name)])
|
||||
for cam_plan_id in cam_plan_ids:
|
||||
assembly_id = cam_plan_id.sf_functional_tool_assembly_id
|
||||
if assembly_id.assemble_status in ('0', '待组装') and not assembly_id.start_preset_bool:
|
||||
logging.info('%s删除成功!!!' % assembly_id)
|
||||
assembly_id.sudo().unlink()
|
||||
logging.info('unlink_cam_plan成功!!!')
|
||||
cam_plan_ids.sudo().unlink()
|
||||
|
||||
|
||||
class FunctionalToolAssembly(models.Model):
|
||||
@@ -543,7 +555,8 @@ class FunctionalToolAssembly(models.Model):
|
||||
after_assembly_functional_tool_name = fields.Char(string='组装后功能刀具名称', readonly=True)
|
||||
after_assembly_functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model',
|
||||
string='组装后功能刀具类型', readonly=True)
|
||||
after_assembly_functional_tool_diameter = fields.Float(string='组装后功能刀具直径(mm)', readonly=True, digits=(10, 3))
|
||||
after_assembly_functional_tool_diameter = fields.Float(string='组装后功能刀具直径(mm)', readonly=True,
|
||||
digits=(10, 3))
|
||||
after_assembly_knife_tip_r_angle = fields.Float(string='组装后刀尖R角(mm)', readonly=True, digits=(10, 3))
|
||||
after_assembly_new_former = fields.Selection([('0', '新'), ('1', '旧')], string='组装后新/旧', readonly=True)
|
||||
cut_time = fields.Integer(string='已切削时间(min)', readonly=True)
|
||||
@@ -557,7 +570,7 @@ class FunctionalToolAssembly(models.Model):
|
||||
after_assembly_alarm_value = fields.Integer(string='组装后报警值(min)', readonly=True)
|
||||
after_assembly_used_value = fields.Integer(string='组装后已使用值(min)', readonly=True)
|
||||
after_assembly_tool_loading_length = fields.Float(string='组装后总长度(mm)', readonly=True, digits=(10, 3))
|
||||
after_assembly_handle_length = fields.Float(string='组装后刀柄长度(mm)',readonly=True, digits=(10, 3))
|
||||
after_assembly_handle_length = fields.Float(string='组装后刀柄长度(mm)', readonly=True, digits=(10, 3))
|
||||
after_assembly_functional_tool_length = fields.Float(string='组装后伸出长(mm)', readonly=True, digits=(10, 3))
|
||||
after_assembly_effective_length = fields.Float(string='组装后有效长(mm)', readonly=True)
|
||||
L_D_number = fields.Float(string='L/D值(mm)', readonly=True)
|
||||
@@ -851,6 +864,10 @@ class FunctionalToolDismantle(models.Model):
|
||||
logging.info('%s刀具确认开始拆解' % self.dismantle_cause)
|
||||
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))
|
||||
location = self.env['stock.location'].search([('name', '=', '刀具组装位置')])
|
||||
location_dest = self.env['stock.location'].search([('name', '=', '刀具房')])
|
||||
# =================刀柄是否[报废]拆解=======
|
||||
|
||||
@@ -162,13 +162,7 @@ class ToolMaterial(models.Model):
|
||||
except Exception as e:
|
||||
logging.info("刀具物料同步失败:%s" % e)
|
||||
|
||||
# @api.model_create_multi
|
||||
# def create(self, vals_list):
|
||||
# records = super(ToolMaterial, self).create(vals_list)
|
||||
# for record in records:
|
||||
# if record:
|
||||
# record.enroll_tool_material()
|
||||
# return records
|
||||
|
||||
|
||||
|
||||
class FunctionalCuttingToolEntity(models.Model):
|
||||
@@ -256,250 +250,208 @@ class FunctionalCuttingToolEntity(models.Model):
|
||||
except Exception as e:
|
||||
logging.info("功能刀具同步失败:%s" % e)
|
||||
|
||||
# @api.model_create_multi
|
||||
# def create(self, vals_list):
|
||||
# records = super(FunctionalCuttingToolEntity, self).create(vals_list)
|
||||
# for record in records:
|
||||
# if record:
|
||||
# record.enroll_functional_tool_entity()
|
||||
# return records
|
||||
|
||||
# def write(self, vals):
|
||||
# res = super().write(vals)
|
||||
# if vals.get('current_location'):
|
||||
# self.enroll_functional_tool_entity()
|
||||
# return res
|
||||
|
||||
#
|
||||
# class FunctionalToolWarning(models.Model):
|
||||
# _inherit = 'sf.functional.tool.warning'
|
||||
# _description = '功能刀具预警注册'
|
||||
#
|
||||
# crea_url = "/api/functional_tool_warning/create"
|
||||
#
|
||||
# # 注册同步功能刀具预警
|
||||
# def enroll_functional_tool_warning(self):
|
||||
# logging.info('调用功能刀具预警注册接口: enroll_functional_tool_warning()')
|
||||
# sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
# token = sf_sync_config['token']
|
||||
# sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
# headers = Common.get_headers(self, token, sf_secret_key)
|
||||
# str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
# objs_all = self.env['sf.functional.tool.warning'].search([('id', '=', self.id)])
|
||||
# self.get_sync_functional_tool_warning(objs_all, str_url, token, headers)
|
||||
#
|
||||
# def sync_enroll_functional_tool_warning_all(self):
|
||||
# logging.info('调用功能刀具预警注册接口: sync_enroll_functional_tool_warning_all()')
|
||||
# sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
# token = sf_sync_config['token']
|
||||
# sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
# headers = Common.get_headers(self, token, sf_secret_key)
|
||||
# str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
# objs_all = self.env['sf.functional.tool.warning'].search([])
|
||||
# self.get_sync_functional_tool_warning(objs_all, str_url, token, headers)
|
||||
#
|
||||
# def get_sync_functional_tool_warning(self, objs_all, str_url, token, headers):
|
||||
# tool_warning_list = []
|
||||
# try:
|
||||
# if objs_all:
|
||||
# for item in objs_all:
|
||||
# val = {
|
||||
# 'id': item.id,
|
||||
# 'name': item.name,
|
||||
# 'code': item.code,
|
||||
# 'rfid': item.rfid,
|
||||
# 'tool_groups_name': item.tool_groups_id.name,
|
||||
# 'production_line': item.production_line_id.name,
|
||||
# 'machine_tool_id': item.maintenance_equipment_id.code,
|
||||
# 'machine_tool_code': item.machine_tool_code,
|
||||
# 'cutter_spacing_code': item.cutter_spacing_code_id.code,
|
||||
# 'functional_tool_name': item.name,
|
||||
# 'barcode': item.barcode_id.name,
|
||||
# 'mrs_cutting_tool_type_code': item.mrs_cutting_tool_type_id.code,
|
||||
# 'diameter': item.diameter,
|
||||
# 'knife_tip_r_angle': item.knife_tip_r_angle,
|
||||
# 'install_tool_time': item.install_tool_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
# 'on_board_time': item.on_board_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
# 'max_lifetime_value': item.max_lifetime_value,
|
||||
# 'alarm_value': item.alarm_value,
|
||||
# 'used_value': item.used_value,
|
||||
# 'functional_tool_status': item.functional_tool_status,
|
||||
# 'alarm_time': item.alarm_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
# 'dispose_user': item.dispose_user,
|
||||
# 'dispose_time': item.dispose_time,
|
||||
# 'dispose_func': item.dispose_func,
|
||||
# }
|
||||
# tool_warning_list.append(val)
|
||||
# kw = json.dumps(tool_warning_list, ensure_ascii=False)
|
||||
# r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
|
||||
# ret = r.json()
|
||||
# if ret.get('code') == 200:
|
||||
# return "功能刀具预警注册成功"
|
||||
# else:
|
||||
# logging.info('没有注册功能刀具预警信息')
|
||||
# except Exception as e:
|
||||
# logging.info("捕获错误信息:%s" % e)
|
||||
#
|
||||
# @api.model_create_multi
|
||||
# def create(self, vals_list):
|
||||
# records = super(FunctionalToolWarning, self).create(vals_list)
|
||||
# for record in records:
|
||||
# if record:
|
||||
# record.enroll_functional_tool_warning()
|
||||
# return records
|
||||
#
|
||||
#
|
||||
# class StockMoveLine(models.Model):
|
||||
# _inherit = 'stock.move.line'
|
||||
# _description = '功能刀具出入库记录注册'
|
||||
#
|
||||
# crea_url = "/api/functional_tool_move/create"
|
||||
#
|
||||
# # 注册同步功能刀具出入库记录
|
||||
# def enroll_functional_tool_move(self):
|
||||
# logging.info('调用功能刀具出入库记录注册接口: enroll_functional_tool_move()')
|
||||
# sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
# token = sf_sync_config['token']
|
||||
# sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
# headers = Common.get_headers(self, token, sf_secret_key)
|
||||
# str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
# objs_all = self.env['stock.move.line'].search([('id', '=', self.id), ('functional_tool_name_id', '!=', False)])
|
||||
# self.get_sync_stock_move_line(objs_all, str_url, token, headers)
|
||||
#
|
||||
# def sync_enroll_functional_tool_move_all(self):
|
||||
# logging.info('调用功能刀具出入库记录注册接口: sync_enroll_functional_tool_move_all()')
|
||||
# sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
# token = sf_sync_config['token']
|
||||
# sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
# headers = Common.get_headers(self, token, sf_secret_key)
|
||||
# str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
# objs_all = self.env['stock.move.line'].search([('functional_tool_name_id', '!=', False)])
|
||||
# self.get_sync_stock_move_line(objs_all, str_url, token, headers)
|
||||
#
|
||||
# def get_sync_stock_move_line(self, objs_all, str_url, token, headers):
|
||||
# tool_stock_list = []
|
||||
# try:
|
||||
# if objs_all:
|
||||
# for item in objs_all:
|
||||
# val = {
|
||||
# 'id': item.id,
|
||||
# 'name': item.functional_tool_name,
|
||||
# 'code': item.code,
|
||||
# 'rfid': item.rfid,
|
||||
# 'tool_groups_name': item.tool_groups_id.name,
|
||||
# 'reference': item.reference,
|
||||
# 'barcode': item.lot_id.name,
|
||||
# 'functional_tool_type_code': item.functional_tool_type_id.code,
|
||||
# 'diameter': item.diameter,
|
||||
# 'knife_tip_r_angle': item.knife_tip_r_angle,
|
||||
# 'install_tool_time': item.install_tool_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
# 'location_id': item.location_id.name,
|
||||
# 'location_dest_name': item.location_dest_id.name,
|
||||
# 'date': item.date.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
# 'qty_done': item.qty_done,
|
||||
# }
|
||||
# tool_stock_list.append(val)
|
||||
# kw = json.dumps(tool_stock_list, ensure_ascii=False)
|
||||
# r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
|
||||
# ret = r.json()
|
||||
# if ret.get('code') == 200:
|
||||
# return "功能刀具出入库记录注册成功"
|
||||
# else:
|
||||
# logging.info('没有注册功能刀具出入库记录信息')
|
||||
# except Exception as e:
|
||||
# logging.info("捕获错误信息:%s" % e)
|
||||
#
|
||||
# @api.model_create_multi
|
||||
# def create(self, vals_list):
|
||||
# records = super(StockMoveLine, self).create(vals_list)
|
||||
# for record in records:
|
||||
# if record.functional_tool_name_id:
|
||||
# record.enroll_functional_tool_move()
|
||||
# return records
|
||||
#
|
||||
#
|
||||
# class RealTimeDistributionFunctionalTools(models.Model):
|
||||
# _inherit = 'sf.real.time.distribution.of.functional.tools'
|
||||
# _description = '功能刀具安全库存注册'
|
||||
#
|
||||
# crea_url = "/api/functional_tool_distribution/create"
|
||||
#
|
||||
# # 注册同步功能刀具预警
|
||||
# def enroll_functional_tool_real_time_distribution(self):
|
||||
# logging.info('调用功能刀具安全库存注册接口: enroll_functional_tool_real_time_distribution()')
|
||||
# sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
# token = sf_sync_config['token']
|
||||
# sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
# headers = Common.get_headers(self, token, sf_secret_key)
|
||||
# str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
# objs_all = self.env['sf.real.time.distribution.of.functional.tools'].search([('id', '=', self.id)])
|
||||
# self.get_sync_real_time_distribution_functional_tools(objs_all, str_url, token, headers)
|
||||
#
|
||||
# def sync_enroll_functional_tool_real_time_distribution_all(self):
|
||||
# logging.info('调用功能刀具安全库存注册接口: sync_enroll_functional_tool_real_time_distribution_all()')
|
||||
# sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
# token = sf_sync_config['token']
|
||||
# sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
# headers = Common.get_headers(self, token, sf_secret_key)
|
||||
# str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
# objs_all = self.env['sf.real.time.distribution.of.functional.tools'].search([])
|
||||
# self.get_sync_real_time_distribution_functional_tools(objs_all, str_url, token, headers)
|
||||
#
|
||||
# def get_sync_real_time_distribution_functional_tools(self, objs_all, str_url, token, headers):
|
||||
# tool_distribution_list = []
|
||||
# try:
|
||||
# if objs_all:
|
||||
# for item in objs_all:
|
||||
# functional_tool_codes = []
|
||||
# for obj in item.sf_functional_tool_entity_ids:
|
||||
# functional_tool_codes.append(obj.code)
|
||||
# val = {
|
||||
# 'id': item.id,
|
||||
# 'name': item.name,
|
||||
# 'tool_groups_name': item.tool_groups_id.name,
|
||||
# 'cutting_tool_type_code': item.sf_cutting_tool_type_id.code,
|
||||
# 'diameter': item.diameter,
|
||||
# 'knife_tip_r_angle': item.knife_tip_r_angle,
|
||||
# 'tool_stock_num': item.tool_stock_num,
|
||||
# 'side_shelf_num': item.side_shelf_num,
|
||||
# 'on_tool_stock_num': item.on_tool_stock_num,
|
||||
# 'tool_stock_total': item.tool_stock_total,
|
||||
# 'min_stock_num': item.min_stock_num,
|
||||
# 'max_stock_num': item.max_stock_num,
|
||||
# 'batch_replenishment_num': item.batch_replenishment_num,
|
||||
# 'unit': item.unit,
|
||||
# 'image': '' if not item.image else base64.b64encode(item.image).decode('utf-8'),
|
||||
# 'functional_tool_codes': str(functional_tool_codes),
|
||||
# 'coarse_middle_thin': item.coarse_middle_thin,
|
||||
# 'whether_standard_knife': item.whether_standard_knife,
|
||||
# 'suitable_machining_method_names': get_suitable_machining_method_names(item),
|
||||
# 'blade_tip_characteristics_name': item.blade_tip_characteristics_id.name,
|
||||
# 'handle_type_name': item.handle_type_id.name,
|
||||
# 'cutting_direction_names': get_cutting_direction_names(item),
|
||||
# 'suitable_coolant_names': get_suitable_coolant_names(item),
|
||||
# 'active': item.active
|
||||
# }
|
||||
# tool_distribution_list.append(val)
|
||||
# kw = json.dumps(tool_distribution_list, ensure_ascii=False)
|
||||
# r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
|
||||
# ret = r.json()
|
||||
# if ret.get('code') == 200:
|
||||
# return "功能刀具出入库记录注册成功"
|
||||
# else:
|
||||
# logging.info('没有注册功能刀具出入库记录信息')
|
||||
# except Exception as e:
|
||||
# logging.info("捕获错误信息:%s" % e)
|
||||
#
|
||||
# @api.model_create_multi
|
||||
# def create(self, vals_list):
|
||||
# records = super(RealTimeDistributionFunctionalTools, self).create(vals_list)
|
||||
# for record in records:
|
||||
# if record:
|
||||
# record.enroll_functional_tool_real_time_distribution()
|
||||
# return records
|
||||
#
|
||||
# def write(self, vals):
|
||||
# res = super().write(vals)
|
||||
# if vals.get('sf_functional_tool_entity_ids') or vals.get('min_stock_num') or vals.get('max_stock_num'):
|
||||
# self.enroll_functional_tool_real_time_distribution()
|
||||
# return res
|
||||
|
||||
class FunctionalToolWarning(models.Model):
|
||||
_inherit = 'sf.functional.tool.warning'
|
||||
_description = '功能刀具预警注册'
|
||||
|
||||
crea_url = "/api/functional_tool_warning/create"
|
||||
|
||||
# 注册同步功能刀具预警
|
||||
def enroll_functional_tool_warning(self):
|
||||
logging.info('调用功能刀具预警注册接口: enroll_functional_tool_warning()')
|
||||
sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
token = sf_sync_config['token']
|
||||
sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
headers = Common.get_headers(self, token, sf_secret_key)
|
||||
str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
objs_all = self.env['sf.functional.tool.warning'].search([('id', '=', self.id)])
|
||||
self.get_sync_functional_tool_warning(objs_all, str_url, token, headers)
|
||||
|
||||
def sync_enroll_functional_tool_warning_all(self):
|
||||
logging.info('调用功能刀具预警注册接口: sync_enroll_functional_tool_warning_all()')
|
||||
sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
token = sf_sync_config['token']
|
||||
sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
headers = Common.get_headers(self, token, sf_secret_key)
|
||||
str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
objs_all = self.env['sf.functional.tool.warning'].search([])
|
||||
self.get_sync_functional_tool_warning(objs_all, str_url, token, headers)
|
||||
|
||||
def get_sync_functional_tool_warning(self, objs_all, str_url, token, headers):
|
||||
tool_warning_list = []
|
||||
try:
|
||||
if objs_all:
|
||||
for item in objs_all:
|
||||
val = {
|
||||
'id': item.id,
|
||||
'name': item.name,
|
||||
'code': item.code,
|
||||
'rfid': item.rfid,
|
||||
'tool_groups_name': item.tool_groups_id.name,
|
||||
'production_line': item.production_line_id.name,
|
||||
'machine_tool_id': item.maintenance_equipment_id.code,
|
||||
'machine_tool_code': item.machine_tool_code,
|
||||
'cutter_spacing_code': item.cutter_spacing_code_id.code,
|
||||
'functional_tool_name': item.name,
|
||||
'barcode': item.barcode_id.name,
|
||||
'mrs_cutting_tool_type_code': item.mrs_cutting_tool_type_id.code,
|
||||
'diameter': item.diameter,
|
||||
'knife_tip_r_angle': item.knife_tip_r_angle,
|
||||
'install_tool_time': item.install_tool_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'on_board_time': item.on_board_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'max_lifetime_value': item.max_lifetime_value,
|
||||
'alarm_value': item.alarm_value,
|
||||
'used_value': item.used_value,
|
||||
'functional_tool_status': item.functional_tool_status,
|
||||
'alarm_time': item.alarm_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'dispose_user': item.dispose_user,
|
||||
'dispose_time': item.dispose_time,
|
||||
'dispose_func': item.dispose_func,
|
||||
}
|
||||
tool_warning_list.append(val)
|
||||
kw = json.dumps(tool_warning_list, ensure_ascii=False)
|
||||
r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
|
||||
ret = r.json()
|
||||
if ret.get('code') == 200:
|
||||
return "功能刀具预警注册成功"
|
||||
else:
|
||||
logging.info('没有注册功能刀具预警信息')
|
||||
except Exception as e:
|
||||
logging.info("捕获错误信息:%s" % e)
|
||||
|
||||
|
||||
class StockMoveLine(models.Model):
|
||||
_inherit = 'stock.move.line'
|
||||
_description = '功能刀具出入库记录注册'
|
||||
|
||||
crea_url = "/api/functional_tool_move/create"
|
||||
|
||||
# 注册同步功能刀具出入库记录
|
||||
def enroll_functional_tool_move(self):
|
||||
logging.info('调用功能刀具出入库记录注册接口: enroll_functional_tool_move()')
|
||||
sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
token = sf_sync_config['token']
|
||||
sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
headers = Common.get_headers(self, token, sf_secret_key)
|
||||
str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
objs_all = self.env['stock.move.line'].search([('id', '=', self.id), ('functional_tool_name_id', '!=', False)])
|
||||
self.get_sync_stock_move_line(objs_all, str_url, token, headers)
|
||||
|
||||
def sync_enroll_functional_tool_move_all(self):
|
||||
logging.info('调用功能刀具出入库记录注册接口: sync_enroll_functional_tool_move_all()')
|
||||
sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
token = sf_sync_config['token']
|
||||
sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
headers = Common.get_headers(self, token, sf_secret_key)
|
||||
str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
objs_all = self.env['stock.move.line'].search([('functional_tool_name_id', '!=', False)])
|
||||
self.get_sync_stock_move_line(objs_all, str_url, token, headers)
|
||||
|
||||
def get_sync_stock_move_line(self, objs_all, str_url, token, headers):
|
||||
tool_stock_list = []
|
||||
try:
|
||||
if objs_all:
|
||||
for item in objs_all:
|
||||
val = {
|
||||
'id': item.id,
|
||||
'name': item.functional_tool_name,
|
||||
'code': item.code,
|
||||
'rfid': item.rfid,
|
||||
'tool_groups_name': item.tool_groups_id.name,
|
||||
'reference': item.reference,
|
||||
'barcode': item.lot_id.name,
|
||||
'functional_tool_type_code': item.functional_tool_type_id.code,
|
||||
'diameter': item.diameter,
|
||||
'knife_tip_r_angle': item.knife_tip_r_angle,
|
||||
'install_tool_time': item.install_tool_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'location_id': item.location_id.name,
|
||||
'location_dest_name': item.location_dest_id.name,
|
||||
'date': item.date.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'qty_done': item.qty_done,
|
||||
}
|
||||
tool_stock_list.append(val)
|
||||
kw = json.dumps(tool_stock_list, ensure_ascii=False)
|
||||
r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
|
||||
ret = r.json()
|
||||
if ret.get('code') == 200:
|
||||
return "功能刀具出入库记录注册成功"
|
||||
else:
|
||||
logging.info('没有注册功能刀具出入库记录信息')
|
||||
except Exception as e:
|
||||
logging.info("捕获错误信息:%s" % e)
|
||||
|
||||
|
||||
class RealTimeDistributionFunctionalTools(models.Model):
|
||||
_inherit = 'sf.real.time.distribution.of.functional.tools'
|
||||
_description = '功能刀具安全库存注册'
|
||||
|
||||
crea_url = "/api/functional_tool_distribution/create"
|
||||
|
||||
# 注册同步功能刀具预警
|
||||
def enroll_functional_tool_real_time_distribution(self):
|
||||
logging.info('调用功能刀具安全库存注册接口: enroll_functional_tool_real_time_distribution()')
|
||||
sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
token = sf_sync_config['token']
|
||||
sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
headers = Common.get_headers(self, token, sf_secret_key)
|
||||
str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
objs_all = self.env['sf.real.time.distribution.of.functional.tools'].search([('id', '=', self.id)])
|
||||
self.get_sync_real_time_distribution_functional_tools(objs_all, str_url, token, headers)
|
||||
|
||||
def sync_enroll_functional_tool_real_time_distribution_all(self):
|
||||
logging.info('调用功能刀具安全库存注册接口: sync_enroll_functional_tool_real_time_distribution_all()')
|
||||
sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
token = sf_sync_config['token']
|
||||
sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
headers = Common.get_headers(self, token, sf_secret_key)
|
||||
str_url = sf_sync_config['sf_url'] + self.crea_url
|
||||
objs_all = self.env['sf.real.time.distribution.of.functional.tools'].search([])
|
||||
self.get_sync_real_time_distribution_functional_tools(objs_all, str_url, token, headers)
|
||||
|
||||
def get_sync_real_time_distribution_functional_tools(self, objs_all, str_url, token, headers):
|
||||
tool_distribution_list = []
|
||||
try:
|
||||
if objs_all:
|
||||
for item in objs_all:
|
||||
functional_tool_codes = []
|
||||
for obj in item.sf_functional_tool_entity_ids:
|
||||
functional_tool_codes.append(obj.code)
|
||||
val = {
|
||||
'id': item.id,
|
||||
'name': item.name,
|
||||
'tool_groups_name': item.tool_groups_id.name,
|
||||
'cutting_tool_type_code': item.sf_cutting_tool_type_id.code,
|
||||
'diameter': item.diameter,
|
||||
'knife_tip_r_angle': item.knife_tip_r_angle,
|
||||
'tool_stock_num': item.tool_stock_num,
|
||||
'side_shelf_num': item.side_shelf_num,
|
||||
'on_tool_stock_num': item.on_tool_stock_num,
|
||||
'tool_stock_total': item.tool_stock_total,
|
||||
'min_stock_num': item.min_stock_num,
|
||||
'max_stock_num': item.max_stock_num,
|
||||
'batch_replenishment_num': item.batch_replenishment_num,
|
||||
'unit': item.unit,
|
||||
'image': '' if not item.image else base64.b64encode(item.image).decode('utf-8'),
|
||||
'functional_tool_codes': str(functional_tool_codes),
|
||||
'coarse_middle_thin': item.coarse_middle_thin,
|
||||
'whether_standard_knife': item.whether_standard_knife,
|
||||
'suitable_machining_method_names': get_suitable_machining_method_names(item),
|
||||
'blade_tip_characteristics_name': item.blade_tip_characteristics_id.name,
|
||||
'handle_type_name': item.handle_type_id.name,
|
||||
'cutting_direction_names': get_cutting_direction_names(item),
|
||||
'suitable_coolant_names': get_suitable_coolant_names(item),
|
||||
'active': item.active
|
||||
}
|
||||
tool_distribution_list.append(val)
|
||||
kw = json.dumps(tool_distribution_list, ensure_ascii=False)
|
||||
r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
|
||||
ret = r.json()
|
||||
if ret.get('code') == 200:
|
||||
return "功能刀具出入库记录注册成功"
|
||||
else:
|
||||
logging.info('没有注册功能刀具出入库记录信息')
|
||||
except Exception as e:
|
||||
logging.info("捕获错误信息:%s" % e)
|
||||
|
||||
@@ -61,6 +61,12 @@ class SfMaintenanceEquipment(models.Model):
|
||||
|
||||
def write_maintenance_equipment_tool(self, datas):
|
||||
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:
|
||||
@@ -128,12 +134,9 @@ class StockLot(models.Model):
|
||||
record.tool_material_status = '报废'
|
||||
else:
|
||||
record.tool_material_status = '未入库'
|
||||
# if record.tool_material_search_id:
|
||||
# # 注册刀具物料状态到cloud平台
|
||||
# record.enroll_tool_material_stock()
|
||||
# elif record.fixture_material_search_id:
|
||||
# # 注册夹具物料状态到cloud平台
|
||||
# record.enroll_fixture_material_stock()
|
||||
if record.fixture_material_search_id:
|
||||
# 注册夹具物料状态到cloud平台
|
||||
record.enroll_fixture_material_stock()
|
||||
|
||||
@api.model
|
||||
def name_search(self, name='', args=None, operator='ilike', limit=100):
|
||||
|
||||
@@ -45,8 +45,8 @@ class ToolMaterial(models.Model):
|
||||
record.have_been_used_num = have_been_used_num
|
||||
record.scrap_num = scrap_num
|
||||
record.number = usable_num + have_been_used_num + scrap_num
|
||||
# 更新数据到cloud的动态数据
|
||||
# record.enroll_tool_material()
|
||||
|
||||
|
||||
|
||||
@api.model
|
||||
def _read_group_cutting_tool_material_id(self, categories, domain, order):
|
||||
|
||||
@@ -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([
|
||||
@@ -859,14 +859,36 @@ class SfStockPicking(models.Model):
|
||||
|
||||
check_in = fields.Char(string='查询是否为入库单', compute='_check_is_in')
|
||||
|
||||
def batch_stock_move(self):
|
||||
"""
|
||||
批量调拨,非就绪状态的会被忽略,完成后有通知提示
|
||||
"""
|
||||
for record in self:
|
||||
if record.state != 'assigned':
|
||||
continue
|
||||
record.action_set_quantities_to_reservation()
|
||||
record.button_validate()
|
||||
|
||||
notification_message = '批量调拨完成!请注意,状态非就绪的单据会被忽略'
|
||||
return {
|
||||
'effect': {
|
||||
'fadeout': 'fast',
|
||||
'message': notification_message,
|
||||
'img_url': '/web/image/%s/%s/image_1024' % (
|
||||
self.create_uid._name, self.create_uid.id) if 0 else '/web/static/img/smile.svg',
|
||||
'type': 'rainbow_man',
|
||||
}
|
||||
}
|
||||
|
||||
@api.depends('name')
|
||||
def _check_is_in(self):
|
||||
"""
|
||||
判断是否为出库单
|
||||
"""
|
||||
if self.name:
|
||||
is_check_in = self.name.split('/')
|
||||
self.check_in = is_check_in[1]
|
||||
for record in self:
|
||||
if record.name:
|
||||
is_check_in = record.name.split('/')
|
||||
record.check_in = is_check_in[1]
|
||||
|
||||
def button_validate(self):
|
||||
"""
|
||||
|
||||
@@ -20,7 +20,7 @@ class MrsShelfLocationDataSync(models.Model):
|
||||
paired_data = list(zip(my_data, their_data))
|
||||
return paired_data
|
||||
|
||||
shelf_1_obj = self.env['sf.shelf'].search([('name', '=', '一号线边刀架')], limit=1)
|
||||
shelf_1_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边刀架')], limit=1)
|
||||
tool_location_objs_1 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_1_obj.id)], order='id')
|
||||
|
||||
location_codes_1 = [location.barcode for location in tool_location_objs_1]
|
||||
@@ -32,7 +32,7 @@ class MrsShelfLocationDataSync(models.Model):
|
||||
aligned_data_1 = align_data(location_codes_1, their_data_1)
|
||||
|
||||
# 2
|
||||
shelf_2_obj = self.env['sf.shelf'].search([('name', '=', '二号线边刀架')], limit=1)
|
||||
shelf_2_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边刀架')], limit=1)
|
||||
tool_location_objs_2 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_2_obj.id)], order='id')
|
||||
|
||||
location_codes_2 = [location.barcode for location in tool_location_objs_2]
|
||||
@@ -44,7 +44,7 @@ class MrsShelfLocationDataSync(models.Model):
|
||||
aligned_data_2 = align_data(location_codes_2, their_data_2)
|
||||
|
||||
# 4
|
||||
shelf_4_obj = self.env['sf.shelf'].search([('name', '=', '一号线边料架')], limit=1)
|
||||
shelf_4_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边料架')], limit=1)
|
||||
tool_location_objs_4 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_4_obj.id)], order='id')
|
||||
|
||||
location_codes_4 = [location.barcode for location in tool_location_objs_4]
|
||||
@@ -56,7 +56,7 @@ class MrsShelfLocationDataSync(models.Model):
|
||||
aligned_data_4 = align_data(location_codes_4, their_data_4)
|
||||
|
||||
# 3
|
||||
shelf_3_obj = self.env['sf.shelf'].search([('name', '=', '一号线边料架')], limit=1)
|
||||
shelf_3_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边料架')], limit=1)
|
||||
tool_location_objs_3 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_3_obj.id)], order='id')
|
||||
|
||||
location_codes_3 = [location.barcode for location in tool_location_objs_3]
|
||||
@@ -68,7 +68,7 @@ class MrsShelfLocationDataSync(models.Model):
|
||||
aligned_data_3 = align_data(location_codes_3, their_data_3)
|
||||
|
||||
# 5
|
||||
shelf_5_obj = self.env['sf.shelf'].search([('name', '=', '一号线边料架')], limit=1)
|
||||
shelf_5_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-三号线边料架')], limit=1)
|
||||
tool_location_objs_5 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_5_obj.id)], order='id')
|
||||
|
||||
location_codes_5 = [location.barcode for location in tool_location_objs_5]
|
||||
|
||||
@@ -149,6 +149,9 @@
|
||||
<button name="action_assign" type="object" string="检查可用量"
|
||||
groups="sf_base.group_sf_stock_user"/>
|
||||
</xpath>
|
||||
<xpath expr="//header" position="inside">
|
||||
<button name="batch_stock_move" type='object' string="批量调拨"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user