申请重新编程
diff --git a/sf_manufacturing/wizard/rework_wizard_views.xml b/sf_manufacturing/wizard/rework_wizard_views.xml
index 08e5f8ef..8ba3f4dd 100644
--- a/sf_manufacturing/wizard/rework_wizard_views.xml
+++ b/sf_manufacturing/wizard/rework_wizard_views.xml
@@ -16,10 +16,10 @@
attrs='{"invisible": [("routing_type","=","装夹预调")]}' widget="many2many_tags"/>
- 注意: 该制造订单的产品已重复编程过 次,且当前编程状态为
+ style='color:red;'/>,且当前编程状态为
Date: Wed, 21 Aug 2024 17:44:22 +0800
Subject: [PATCH 62/70] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8E=A5=E5=8F=A3?=
=?UTF-8?q?=EF=BC=8C=E4=BD=BF=E5=85=B6=E6=98=93=E4=BA=8E=E5=8F=96=E5=80=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_machine_connect/controllers/controllers.py | 95 +++++++++++++++----
1 file changed, 75 insertions(+), 20 deletions(-)
diff --git a/sf_machine_connect/controllers/controllers.py b/sf_machine_connect/controllers/controllers.py
index 0a770f9d..51a5bd92 100644
--- a/sf_machine_connect/controllers/controllers.py
+++ b/sf_machine_connect/controllers/controllers.py
@@ -376,7 +376,7 @@ class Sf_Dashboard_Connect(http.Controller):
:param kw:
:return:
"""
- res = {'status': 1, 'message': '成功', 'data': []}
+ res = {'status': 1, 'message': '成功', 'data': {}}
plan_obj = request.env['sf.production.plan'].sudo()
line_list = ast.literal_eval(kw['line_list'])
begin_time_str = kw['begin_time'].strip('"')
@@ -409,24 +409,73 @@ class Sf_Dashboard_Connect(http.Controller):
'date': date.strftime('%Y-%m-%d'),
'order_count': len(orders)
})
+ # 外面包一层,没什么是包一层不能解决的,包一层就能区分了,类似于包一层div
+ # 外面包一层的好处是,可以把多个数据结构打包在一起,方便前端处理
- res['data'] = order_counts
- return json.dumps(res)
+ # date_list_dict = {line: order_counts}
- # # 实时产量
- # @http.route('/api/RealTimeProduct', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
- # def RealTimeProduct(self, **kw):
- # """
- # 获取实时产量
- # :param kw:
- # :return:
- # """
- #
- # def get_real_time_product(line_list):
- # res = {'status': 1, 'message': '成功', 'data': []}
- # plan_obj = request.env['sf.production.plan'].sudo()
- # for line in line_list:
- # plan_data = plan_obj.search([('production_line_id.name', '=', line)])
+ res['data'][line] = order_counts
+ return json.dumps(res)
+
+ # 实时产量
+ @http.route('/api/RealTimeProduct', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
+ def RealTimeProduct(self, **kw):
+ """
+ 获取实时产量
+ :param kw:
+ :return:
+ """
+ res = {'status': 1, 'message': '成功', 'data': {}}
+ plan_obj = request.env['sf.production.plan'].sudo()
+ line_list = ast.literal_eval(kw['line_list'])
+ begin_time_str = kw['begin_time'].strip('"')
+ end_time_str = kw['end_time'].strip('"')
+ begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S')
+ end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
+
+ def get_hourly_intervals(start_time, end_time):
+ intervals = []
+ current_time = start_time
+ while current_time < end_time:
+ next_hour = current_time + timedelta(hours=1)
+ intervals.append((current_time, min(next_hour, end_time)))
+ current_time = next_hour
+ return intervals
+
+ # 当班计划量
+ for line in line_list:
+ plan_order_nums = plan_obj.search_count(
+ [('production_line_id.name', '=', line), ('state', 'not in', ['draft']),
+ ('date_planned_start', '>=', begin_time),
+ ('date_planned_start', '<', end_time)
+ ])
+ finish_order_nums = plan_obj.search_count(
+ [('production_line_id.name', '=', line), ('state', 'in', ['finished']),
+ ('date_planned_start', '>=', begin_time),
+ ('date_planned_start', '<', end_time)
+ ])
+ hourly_intervals = get_hourly_intervals(begin_time, end_time)
+ production_counts = []
+
+ for start, end in hourly_intervals:
+ orders = plan_obj.search([
+ ('actual_end_time', '>=', start.strftime('%Y-%m-%d %H:%M:%S')),
+ ('actual_end_time', '<', end.strftime('%Y-%m-%d %H:%M:%S')),
+ ('production_line_id.name', '=', line)
+ ])
+ production_counts.append({
+ 'start_time': start.strftime('%Y-%m-%d %H:%M:%S'),
+ 'end_time': end.strftime('%Y-%m-%d %H:%M:%S'),
+ 'production_count': len(orders)
+ })
+ production_counts_dict = {'production_counts': production_counts,
+ 'plan_order_nums': plan_order_nums,
+ 'finish_order_nums': finish_order_nums,
+ }
+
+ res['data'][line] = production_counts_dict
+ # res['data'].append({line: production_counts})
+ return json.dumps(res)
# 工单明细
@http.route('/api/OrderDetail', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
@@ -437,7 +486,8 @@ class Sf_Dashboard_Connect(http.Controller):
:return:
"""
- res = {'status': 1, 'message': '成功', 'not_done_data': [], 'done_data': []}
+ # res = {'status': 1, 'message': '成功', 'not_done_data': [], 'done_data': []}
+ res = {'status': 1, 'message': '成功', 'data': {}}
plan_obj = request.env['sf.production.plan'].sudo()
line_list = ast.literal_eval(kw['line_list'])
begin_time_str = kw['begin_time'].strip('"')
@@ -445,6 +495,9 @@ class Sf_Dashboard_Connect(http.Controller):
begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S')
end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
print('line_list: %s' % line_list)
+ not_done_data = []
+ done_data = []
+ final_data = {}
for line in line_list:
# 未完成订单
@@ -506,7 +559,7 @@ class Sf_Dashboard_Connect(http.Controller):
'state': state_dict[order.state],
}
- res['not_done_data'].append(line_dict)
+ not_done_data.append(line_dict)
for finish_order in finish_orders:
blank_name = ''
@@ -532,6 +585,8 @@ class Sf_Dashboard_Connect(http.Controller):
'finish_time': finish_order.actual_end_time.strftime('%Y-%m-%d %H:%M:%S'),
}
- res['done_data'].append(line_dict)
+ done_data.append(line_dict)
+ # 开始包一层
+ res['data'][line] = {'not_done_data': not_done_data, 'done_data': done_data}
return json.dumps(res)
From 3d2c62f5dbf4d7c37d41dc0b0a7c31c54a08b7b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?=
Date: Wed, 21 Aug 2024 20:16:41 +0800
Subject: [PATCH 63/70] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=85=8D=E9=80=81?=
=?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BF=AE=E6=94=B9=E5=B7=A5=E4=BB=B6=E9=85=8D?=
=?UTF-8?q?=E9=80=81=E5=8D=95=E7=9A=84bug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_manufacturing/models/agv_scheduling.py | 4 ++--
sf_manufacturing/models/mrp_workorder.py | 16 ++++++++--------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/sf_manufacturing/models/agv_scheduling.py b/sf_manufacturing/models/agv_scheduling.py
index f2ac517b..7902b469 100644
--- a/sf_manufacturing/models/agv_scheduling.py
+++ b/sf_manufacturing/models/agv_scheduling.py
@@ -242,13 +242,13 @@ class AgvScheduling(models.Model):
elif vals['state'] == '已配送':
self.env['sf.workpiece.delivery'].search([('agv_scheduling_id', '=', self.id)]).write({
'status': '已配送',
- 'feeder_station_destination_id': self.end_site_id,
+ 'feeder_station_destination_id': self.end_site_id.id,
'route_id': self.agv_route_id.id,
'task_completion_time': fields.Datetime.now()
})
elif vals['state'] == '配送中':
self.env['sf.workpiece.delivery'].search([('agv_scheduling_id', '=', self.id)]).write({
- 'feeder_station_destination_id': self.end_site_id,
+ 'feeder_station_destination_id': self.end_site_id.id,
'route_id': self.agv_route_id.id,
'task_delivery_time': fields.Datetime.now()
})
diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py
index bb1cfce3..40382c39 100644
--- a/sf_manufacturing/models/mrp_workorder.py
+++ b/sf_manufacturing/models/mrp_workorder.py
@@ -1657,14 +1657,14 @@ class WorkPieceDelivery(models.Model):
obj.feeder_station_start_id.name, obj.feeder_station_destination_id.name)
return obj
- @api.constrains('route_id')
- def _check_route_id(self):
- if self.type == '运送空料架':
- 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('route_id')
+ # def _check_route_id(self):
+ # if self.type == '运送空料架':
+ # 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):
From 9e356682dc806e47b7e59f46771b46138d2b50e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?=
Date: Thu, 22 Aug 2024 10:22:35 +0800
Subject: [PATCH 64/70] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=A5=E9=A9=B3?=
=?UTF-8?q?=E7=AB=99=E7=8A=B6=E6=80=81=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_manufacturing/controllers/controllers.py | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py
index 95bb52c6..af5e1a1f 100644
--- a/sf_manufacturing/controllers/controllers.py
+++ b/sf_manufacturing/controllers/controllers.py
@@ -638,9 +638,14 @@ class Manufacturing_Connect(http.Controller):
request.env['center_control.interface.log'].sudo().create(
{'content': ret, 'name': 'AutoDeviceApi/AGVStationState'})
logging.info('ret:%s' % ret)
- if 'DeviceId' in ret and 'AtHome' in ret:
- logging.info('DeviceId:%s, AtHome:%s' % (ret['DeviceId'], ret['AtHome']))
- request.env['sf.agv.site'].update_site_state({ret['DeviceId']: '占用' if ret['AtHome'] else '空闲'})
+ ret = ret['param']
+ params = {}
+ for i in range(len(ret)):
+ if 'DeviceId' in ret[i] and 'AtHome' in ret[i]:
+ logging.info('DeviceId:%s, AtHome:%s' % (ret[i]['DeviceId'], ret[i]['AtHome']))
+ params[ret[i]['DeviceId']] = '占用' if ret[i]['AtHome'] else '空闲'
+ if params:
+ request.env['sf.agv.site'].update_site_state(params)
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)}
logging.info('AGVDownProduct error:%s' % e)
From 39bc206344abfad09a6a37140956ac39bba33e1c Mon Sep 17 00:00:00 2001
From: yuxianghui <3437689193@qq.com>
Date: Thu, 22 Aug 2024 10:31:22 +0800
Subject: [PATCH 65/70] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E8=B4=A7?=
=?UTF-8?q?=E4=BD=8D=E4=BF=A1=E6=81=AF=E6=8E=A5=E5=8F=A3=E3=80=81=E5=BA=93?=
=?UTF-8?q?=E4=BD=8D=E5=8F=98=E6=9B=B4=E6=8E=A5=E5=8F=A3=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_manufacturing/controllers/controllers.py | 11 ++++++-----
sf_warehouse/models/sync_common.py | 11 ++++++-----
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py
index 6319c050..f35e47ed 100644
--- a/sf_manufacturing/controllers/controllers.py
+++ b/sf_manufacturing/controllers/controllers.py
@@ -436,6 +436,7 @@ class Manufacturing_Connect(http.Controller):
DeciveId)))
total_data = request.env['sf.shelf.location.datasync'].sudo().get_total_data()
for item in shelfinfo:
+ logging.info('货架已获取信息:%s' % item)
shelf_barcode = request.env['sf.shelf.location.datasync'].sudo().find_our_code(
total_data, item['Postion'])
location_id = request.env['sf.shelf.location'].sudo().search(
@@ -450,15 +451,15 @@ class Manufacturing_Connect(http.Controller):
if tool:
location_id.product_sn_id = tool.barcode_id.id
# 修改功能刀具状态
- tool_state = {'Nomal': '正常', 'Warning': '报警'}
- if tool_state.get(item.get('State')):
- if tool_state.get(item.get('State')) != tool.functional_tool_status:
+ if item.get('State') == '报警':
+ if tool.functional_tool_status != item.get('State'):
tool.write({
- 'functional_tool_status': tool_state.get(item['State'])
+ 'functional_tool_status': item['State']
})
else:
location_id.product_sn_id = False
- logging.info('货架已获取信息:%s' % item)
+ if item['RfidCode']:
+ logging.info('Rfid为【%s】的功能刀具在系统中不存在!' % item['RfidCode'])
else:
equipment_id = request.env['maintenance.equipment'].sudo().search([('name', '=', DeciveId)])
if equipment_id:
diff --git a/sf_warehouse/models/sync_common.py b/sf_warehouse/models/sync_common.py
index 3d28583c..aaa186f9 100644
--- a/sf_warehouse/models/sync_common.py
+++ b/sf_warehouse/models/sync_common.py
@@ -110,6 +110,7 @@ class MrsShelfLocationDataSync(models.Model):
total_data = self.get_total_data()
print('shelfinfo:', shelfinfo)
for item in shelfinfo:
+ logging.info('货架已获取信息:%s' % item)
shelf_barcode = self.find_our_code(total_data, item['Postion'])
location_id = self.env['sf.shelf.location'].search([('barcode', '=', shelf_barcode)], limit=1)
if location_id:
@@ -121,14 +122,15 @@ class MrsShelfLocationDataSync(models.Model):
if tool:
location_id.product_sn_id = tool.barcode_id.id
# 修改功能刀具状态
- tool_state = {'Nomal': '正常', 'Warning': '报警'}
- if tool_state.get(item.get('State')):
- if tool_state.get(item.get('State')) != tool.functional_tool_status:
+ if item.get('State') == '报警':
+ if tool.functional_tool_status != item.get('State'):
tool.write({
- 'functional_tool_status': tool_state.get(item['State'])
+ 'functional_tool_status': item['State']
})
else:
location_id.product_sn_id = False
+ if item['RfidCode']:
+ logging.info('Rfid为【%s】的功能刀具在系统中不存在!' % item['RfidCode'])
else:
stock_lot_obj = self.env['stock.lot'].search([('rfid', '=', item['RfidCode'])], limit=1)
if stock_lot_obj:
@@ -136,7 +138,6 @@ class MrsShelfLocationDataSync(models.Model):
else:
location_id.product_sn_id = False
- logging.info('货架已获取信息:%s' % item)
except Exception as e:
logging.info("捕获错误信息:%s" % e)
raise ValidationError("数据错误导致同步失败,请联系管理员")
From d13961ff5fa8c536b842a42bc6326455fc39fa33 Mon Sep 17 00:00:00 2001
From: "jinling.yang"
Date: Thu, 22 Aug 2024 10:52:19 +0800
Subject: [PATCH 66/70] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8A=A5=E5=BA=9F-?=
=?UTF-8?q?=E6=8B=A3=E8=B4=A7=E5=8D=95=EF=BC=88sfp=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_manufacturing/models/mrp_production.py | 15 +++++++++++----
.../views/mrp_production_addional_change.xml | 2 +-
sf_manufacturing/wizard/production_wizard.py | 5 +++++
3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py
index 466e9a62..8e1f7199 100644
--- a/sf_manufacturing/models/mrp_production.py
+++ b/sf_manufacturing/models/mrp_production.py
@@ -797,7 +797,7 @@ class MrpProduction(models.Model):
})
return action
- # 返工
+ # 报废
def button_scrap_new(self):
cloud_programming = self._cron_get_programming_state()
return {
@@ -969,12 +969,12 @@ class MrpProduction(models.Model):
'location_dest_id', '=', self.env['stock.location'].search([('parent_path', '=', '2/5/')]).id),
('location_src_id', '=', self.env['stock.location'].search(
[('barcode', '=', 'CP')]).id)])
- origin = move._prepare_procurement_origin()
+ # origin = move._prepare_procurement_origin()
procurement_requests.append(self.env['procurement.group'].Procurement(
move.product_id, 1.0, move.product_uom,
self.env['stock.location'].search([('barcode', '=', 'CP')]),
rule and rule.name or "/",
- origin, move.company_id, move_values))
+ sale_order.name, move.company_id, move_values))
self.env['procurement.group'].run(procurement_requests,
raise_user_error=not self.env.context.get('from_orderpoint'))
# self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
@@ -986,7 +986,6 @@ class MrpProduction(models.Model):
[('origin', '=', self.origin)], order='id desc', limit=1)
move = self.env['stock.move'].search([('origin', '=', productions.name)], order='id desc')
for mo in move:
- print(mo.id)
if mo.procure_method == 'make_to_order' and mo.name != productions.name:
if mo.name == '/':
domain = [('barcode', '=', 'WH-PC'), ('sequence_code', '=', 'PC')]
@@ -1001,6 +1000,14 @@ class MrpProduction(models.Model):
if mo.production_id:
if mo.production_id != productions:
mo.production_id = False
+ mo_move = self.env['stock.move'].search(
+ [('origin', '=', sale_order.name), ('reference', 'ilike', 'WH/MO/')])
+ if mo_move:
+ sfp_move = self.env['stock.move'].search(
+ [('origin', '=', sale_order.name), ('reference', 'ilike', 'WH/SFP/')], limit=1)
+ mo_move.write({'reference': sfp_move.reference, 'partner_id': sfp_move.partner_id.id,
+ 'picking_id': sfp_move.picking_id.id, 'picking_type_id': sfp_move.picking_type_id.id,
+ 'production_id': False})
productions.write({'programming_no': self.programming_no, 'is_remanufacture': True})
productions.procurement_group_id.mrp_production_ids.move_dest_ids.write(
{'group_id': self.env['procurement.group'].search([('name', '=', sale_order.name)])})
diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml
index b1c1ff1e..99d27576 100644
--- a/sf_manufacturing/views/mrp_production_addional_change.xml
+++ b/sf_manufacturing/views/mrp_production_addional_change.xml
@@ -130,7 +130,7 @@
attrs="{'invisible': ['|',('state', '!=', 'rework') ,('programming_state', '!=', '已编程')]}"/>
+ attrs="{'invisible': ['|',('is_scrap', '=', False),('state','=','cancel')]}"/>
0 else 0), 3)
@@ -356,6 +372,7 @@ class Sf_Dashboard_Connect(http.Controller):
'plan_data_fault_counts': plan_data_fault_counts,
'finishe_rate': finishe_rate,
'plan_data_progress_deviation': plan_data_progress_deviation,
+ 'plan_data_rework_counts': plan_data_rework_counts
}
res['data'][line] = data
@@ -405,9 +422,22 @@ class Sf_Dashboard_Connect(http.Controller):
(date_field_name, '>=', date.strftime('%Y-%m-%d 00:00:00')),
(date_field_name, '<', next_day.strftime('%Y-%m-%d 00:00:00'))
])
+
+ rework_orders = plan_obj.search(
+ [('production_line_id.name', '=', line), ('state', 'in', ['rework']),
+ (date_field_name, '>=', date.strftime('%Y-%m-%d 00:00:00')),
+ (date_field_name, '<', next_day.strftime('%Y-%m-%d 00:00:00'))
+ ])
+ not_passed_orders = plan_obj.search(
+ [('production_line_id.name', '=', line), ('state', 'in', ['scrap', 'cancel']),
+ (date_field_name, '>=', date.strftime('%Y-%m-%d 00:00:00')),
+ (date_field_name, '<', next_day.strftime('%Y-%m-%d 00:00:00'))
+ ])
order_counts.append({
'date': date.strftime('%Y-%m-%d'),
- 'order_count': len(orders)
+ 'order_count': len(orders),
+ 'rework_orders': len(rework_orders),
+ 'not_passed_orders': len(not_passed_orders)
})
# 外面包一层,没什么是包一层不能解决的,包一层就能区分了,类似于包一层div
# 外面包一层的好处是,可以把多个数据结构打包在一起,方便前端处理
@@ -590,3 +620,91 @@ class Sf_Dashboard_Connect(http.Controller):
# 开始包一层
res['data'][line] = {'not_done_data': not_done_data, 'done_data': done_data}
return json.dumps(res)
+
+ # 查询pg库来获得待机次数
+ @http.route('/api/IdleAlarmCount', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
+ def idle_count(self, **kw):
+ """
+ 查询设备的待机次数
+ """
+ res = {'status': 1, 'message': '成功', 'data': {}}
+ logging.info('前端请求机床数据的参数为:%s' % kw)
+
+ # 连接数据库
+ conn = psycopg2.connect(**db_config)
+ cur = conn.cursor()
+ try:
+ # 获取请求的机床数据
+ machine_list = ast.literal_eval(kw['machine_list'])
+ idle_times = []
+ idle_dict = {}
+
+ for item in machine_list:
+ sql = '''
+ SELECT idle_start_time,alarm_time,alarm_repair_time FROM device_data WHERE device_name = %s;
+ '''
+ # 执行SQL命令
+ cur.execute(sql, (item,))
+ result = cur.fetchall()
+ # # print('result', result)
+ #
+ # # 将查询结果添加到idle_times列表中
+ # idle_times = [row[0] for row in result if row[0] is not None]
+ #
+ # # 对结果去重
+ # unique_idle_times = set(idle_times)
+ # # print('unique_idle_times', unique_idle_times)
+ #
+ # # 统计去重后的数量
+ # idle_count = len(unique_idle_times)
+ # # idle_dict[item] = idle_count
+ #
+ # res['data'][item] = idle_count
+
+ total_alarm_time = 0
+ alarm_count = 0
+ alarm_time_list = []
+ idle_times = []
+ alarm_times = []
+
+ for row in result:
+ idle_start_time = row[0]
+ alarm_time = row[1]
+ alarm_repair_time = row[2]
+
+ alarm_time_list.append(alarm_time) # 将时长累加,以秒为单位
+ idle_times.append(idle_start_time)
+ # if alarm_repair_time is not None:
+ # alarm_times.append(alarm_repair_time)
+ alarm_times.append(alarm_repair_time)
+
+ # 对结果去重
+ unique_total_alarm_time = set(alarm_time_list)
+ unique_idle_times = set(idle_times)
+ unique_alarm_times = set(alarm_times)
+
+ # 统计去重后的数量
+ idle_count = len(unique_idle_times)
+
+ for alarm_time in unique_total_alarm_time:
+ if alarm_time is not None:
+ total_alarm_time += abs(float(alarm_time))
+
+ alarm_count = len(unique_alarm_times) if unique_alarm_times else 0
+ alarm_count = alarm_count if total_alarm_time else 0
+
+ # 存储待机次数和总待机时长(单位:秒)
+ res['data'][item] = {
+ 'idle_count': idle_count,
+ 'total_alarm_time': total_alarm_time / 3600, # 以秒为单位
+ 'alarm_count': alarm_count
+ }
+
+ # 返回统计结果
+ return json.dumps(res)
+ except Exception as e:
+ print(f"An error occurred: {e}")
+ return json.dumps(res)
+ finally:
+ cur.close()
+ conn.close()
diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py
index 6f6a4be9..a69160cb 100644
--- a/sf_manufacturing/models/mrp_workorder.py
+++ b/sf_manufacturing/models/mrp_workorder.py
@@ -1167,6 +1167,9 @@ class ResMrpWorkOrder(models.Model):
record.process_state = '待解除装夹'
# record.write({'process_state': '待加工'})
record.production_id.process_state = '待解除装夹'
+ self.env['sf.production.plan'].sudo().search([('name', '=', record.production_id.name)]).write({
+ 'state': 'finished'
+ })
record.production_id.write({'detection_result_ids': [(0, 0, {
'rework_reason': record.reason,
'detailed_reason': record.detailed_reason,
From 296659ebb0a8c1fbe216c688e1f6daf19030df1f Mon Sep 17 00:00:00 2001
From: mgw <1392924357@qq.com>
Date: Fri, 23 Aug 2024 11:44:05 +0800
Subject: [PATCH 70/70] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=BC=82=E5=B8=B8?=
=?UTF-8?q?=E6=98=8E=E7=BB=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_machine_connect/controllers/controllers.py | 55 +++++++++++++++++++
sf_manufacturing/models/mrp_workorder.py | 3 +-
2 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/sf_machine_connect/controllers/controllers.py b/sf_machine_connect/controllers/controllers.py
index a40b148d..946bb78c 100644
--- a/sf_machine_connect/controllers/controllers.py
+++ b/sf_machine_connect/controllers/controllers.py
@@ -708,3 +708,58 @@ class Sf_Dashboard_Connect(http.Controller):
finally:
cur.close()
conn.close()
+
+ # 查询pg库来获得异常情况
+ @http.route('/api/alarm/logs', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
+ def idle_count(self, **kw):
+ """
+ 查询设备的异常情况
+ """
+ res = {'status': 1, 'message': '成功', 'data': {}}
+ logging.info('前端请求机床数据的参数为:%s' % kw)
+
+ # 连接数据库
+ conn = psycopg2.connect(**db_config)
+ cur = conn.cursor()
+ try:
+ # 获取请求的机床数据
+ # machine_list = ast.literal_eval(kw['machine_list'])
+ # idle_times = []
+ # idle_dict = {}
+
+ # for item in machine_list:
+ sql = '''
+ SELECT DISTINCT ON (alarm_time) alarm_time, alarm_message, system_date, system_time, alarm_repair_time
+ FROM device_data
+ WHERE alarm_time IS NOT NULL
+ ORDER BY alarm_time, time;
+
+ '''
+ # 执行SQL命令
+ cur.execute(sql)
+ result = cur.fetchall()
+ print('result', result)
+
+ # 将查询结果转换为字典列表
+ data = []
+ for row in result:
+ record = {
+ 'alarm_time': row[0],
+ 'alarm_message': row[1],
+ 'system_date': row[2],
+ 'system_time': row[3],
+ 'alarm_repair_time': row[4]
+ }
+ data.append(record)
+
+ # 将数据填充到返回结果中
+ res['data'] = data
+
+ # 返回统计结果
+ return json.dumps(res, ensure_ascii=False)
+ except Exception as e:
+ print(f"An error occurred: {e}")
+ return json.dumps(res)
+ finally:
+ cur.close()
+ conn.close()
diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py
index abe08c48..066cb133 100644
--- a/sf_manufacturing/models/mrp_workorder.py
+++ b/sf_manufacturing/models/mrp_workorder.py
@@ -1168,7 +1168,8 @@ class ResMrpWorkOrder(models.Model):
# record.write({'process_state': '待加工'})
record.production_id.process_state = '待解除装夹'
self.env['sf.production.plan'].sudo().search([('name', '=', record.production_id.name)]).write({
- 'state': 'finished'
+ 'state': 'finished',
+ 'actual_end_time': datetime.now()
})
record.production_id.write({'detection_result_ids': [(0, 0, {
'rework_reason': record.reason,