SCTMES_V5/mes_in_sct/app/action/SetTrayProcessResult.php
2025-06-14 18:55:09 +08:00

443 lines
19 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\action;
use libs\listener\Event;
use libs\db\Db;
use Exception;
class SetTrayProcessResult
{
public function execute($post)
{
// 验证数据
$param = check_valid($post['action'], [
['tray', 'string', '托盘号'],
['workingsubclass', 'string', '工序单元'],
['device_code', 'string', '设备号']
], $post['param']);
$date = date('Y-m-d H:i:s');
$param['CHANNEL'] = [];
$param['DEVICE_CODE'] = [];
$param['FINISH_TIME'] = [];
try {
// 判断托盘是否激活中
$sql = sprintf(
"SELECT a.tray,a.lot,a.batch,a.subbatch,a.next_process_code,a.date_log,b.flow_id
FROM hf_mes_production_tray_map AS a
INNER JOIN hf_mes_production_planning_management_batch AS b ON b.batch = a.batch
WHERE a.tray='%s' AND a.active=1 LIMIT 1;",
$param['tray']
);
$ret = Db::fetch($sql);
if (empty($ret)) {
throw new Exception("托盘[{$param['tray']}]不是激活状态");
}
list($tray, $lot, $batch, $subbatch, $flow_id, $date_log, $workingsubclass) = [
$ret['tray'],
$ret['lot'],
$ret['batch'],
$ret['subbatch'],
$ret['flow_id'],
json_decode($ret['date_log'], true),
$param['workingsubclass']
];
// 验证设备
$device_code = '';
if (!isset($param['device_code']) || empty($param['device_code'])) {
$sql = sprintf(
"SELECT code
FROM hf_mes_device
WHERE ip='%s' LIMIT 1;",
$post['client_id']
);
$ret_device = Db::fetch($sql);
if (!empty($ret_device)) {
$device_code = $ret_device['device_code'];
}
} else {
$device_code = $param['device_code'];
}
if (empty($device_code)) {
throw new Exception("请上传设备数据[device_code]");
}
// 验证当前工序与系统工序是否一致
$current_process_code = "{$flow_id}_{$workingsubclass}";
if ($ret['next_process_code'] !== $current_process_code) {
throw new Exception("设备当前工序[{$current_process_code}]与系统当前工序[{$ret['next_process_code']}]不一致");
}
// 获取工序
$sql = sprintf(
"SELECT a.id,a.pin_check,b.process AS flow_process
FROM hf_mes_technology_process AS a
INNER JOIN hf_mes_technology_flow AS b ON b.id = a.flow_id
WHERE a.code='%s' LIMIT 1;",
$current_process_code
);
$ret = Db::fetch($sql);
if (empty($ret)) {
throw new Exception("托盘[{$tray}],获取工序数据失败!");
}
list($flow_process, $pin_check, $process_id) = [
json_decode($ret['flow_process'], true),
$ret['pin_check'],
$ret['id']
];
// 获取BKV的电池数据
$sql = sprintf(
"SELECT battery_id, active
FROM \"%s\"
WHERE tray='%s' AND lot='%s'
ORDER BY id ASC;",
config('app.bkv_prefix') . $subbatch,
$tray,
$lot
);
$bkv_ret = Db::fetchAll($sql);
if (empty($bkv_ret)) {
throw new Exception("托盘[{$tray}]的电池数据不存在[bkv]");
}
$bkv_battery_ids = array_column($bkv_ret, 'battery_id');
$bkv_actives = array_column($bkv_ret, 'active');
// 根据电池数组赋予通道数据
$param['CHANNEL'] = array_map(function ($value) {
return $value + 1;
}, array_keys($bkv_battery_ids));
// 赋予设备结果参数数组
$param['DEVICE_CODE'] = array_pad($param['DEVICE_CODE'], count($bkv_battery_ids), $device_code);
// 赋予完成时间结果参数数组
$param['FINISH_TIME'] = array_pad($param['FINISH_TIME'], count($bkv_battery_ids), $date);
// 验证pin_check数据
if ($pin_check) {
Event::emit('SetTrayProcessResultEvent.verifyPinCheck', [
'param' => $param,
'battery_ids' => $bkv_battery_ids,
]);
}
// 刷选出需要设备上传的结果参数
$sql = sprintf(
"SELECT code,field_type,is_upload
FROM hf_mes_technology_process_result_param
WHERE process_id=%s AND is_upload=1;",
$process_id
);
$result_param_need = Db::fetchAll($sql);
if (!empty($result_param_need)) {
$result_param_need_params = array_column($result_param_need, 'code');
$result_param_need_column = array_column($result_param_need, NULL, 'code');
// 验证提交的结果数据
// 1、验证是否上传了结果参数
$diff = array_diff($result_param_need_params, array_keys($param));
if (!empty($diff)) {
throw new Exception("结果参数:[" . implode(',', $diff) . "]没有上传");
}
// 1、验证结果参数的数组长度是否与电池数量一致
// 2、验证具体的结果数据有没有上传与数据的类型
foreach ($result_param_need as $idx => $item) {
// 1、验证结果参数的数组长度是否与电池数量一致
if (count($param[$item['code']]) != count($bkv_battery_ids)) {
$count = count($bkv_battery_ids);
throw new Exception("结果参数[{$item['code']}]的数组长度与电池数量不相等,电池数量为:[{$count}],请检查");
}
// 结果参数数组
$p_vals = $param[$item['code']];
// 结果参数类型
$p_class = $item['field_type'];
// 2、验证具体的结果数据有没有上传与数据的类型
foreach ($p_vals as $p_key => $p_val) {
if ($p_class == 'TIMESTAMP') {
if ($p_val != "" && date('Y-m-d H:i:s', strtotime($p_val)) != $p_val) {
throw new Exception(sprintf(
"结果数据[%s]第[%s]位置的数据类型与系统[%s]类型要求不相符,请检查!【要求数据类型格式比如为:'2022-11-11 09:00:00'】",
$item['code'],
$p_key + 1,
$p_class
));
}
} elseif ($p_class == 'FLOAT') {
if ($p_val != "" && !is_numeric($p_val)) {
throw new Exception(sprintf(
"结果数据[%s]第[%s]位置的数据类型与系统[%s]类型要求不相符,请检查!【要求数据类型格式比如为: 12.8】",
$item['code'],
$p_key + 1,
$p_class
));
}
} elseif ($p_class == 'INT') {
if ($p_val != "" && !is_int($p_val)) {
throw new Exception(sprintf(
"结果数据[%s]第[%s]位置的数据类型与系统[%s]类型要求不相符,请检查!【要求数据类型格式比如为: 12】",
$item['code'],
$p_key + 1,
$p_class
));
}
}
}
}
} else {
$result_param_need = [];
}
// 把完成时间加入到结果参数上传之中
array_push(
$result_param_need,
['code' => 'FINISH_TIME', 'field_type' => 'TIMESTAMP', 'is_upload' => 0],
['code' => 'DEVICE_CODE', 'field_type' => 'VARCHAR', 'is_upload' => 0],
['code' => 'CHANNEL', 'field_type' => 'INT', 'is_upload' => 0]
);
// 计算温度补偿
$param = Event::emit('SetTrayProcessResultEvent.getTemperatureSupp', [
'param' => $param,
'flow_id' => $flow_id,
'process_id' => $process_id,
'process_code' => $current_process_code
]);
// 判断是否有下下一个工序
$flow_process_column = array_column($flow_process, NULL, '2');
$current_process_idx = $flow_process_column[$current_process_code][0];
$next_next_process_code = -1; // 如果没有下下工序,那么当前工序就是结束工序
if (isset($flow_process[$current_process_idx + 1][2])) {
$next_next_process_code = $flow_process[$current_process_idx + 1][2];
}
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
// 开启事务
Db::beginTrans();
try {
// 标记最后一条数据的状态
Event::emit('SetProcessLogEvent.updateLastStatus', $bkv_battery_ids);
// 更改BKV数据
$common_update_str = sprintf(
"process_code='%s',process_idx=%s,next_process_code='%s'",
$current_process_code,
$current_process_idx,
$next_next_process_code
);
// 判断如果是最后一个工序,拼接取消激活的状态修改
if ($next_next_process_code == -1) {
$common_update_str = $common_update_str . ',active=0';
}
// process_log数据
$insert_process_log_data = [];
foreach ($bkv_battery_ids as $battery_index => $battery_id) {
// 过滤0的数据和未激活的电池数据
$active = $bkv_actives[$battery_index];
// 过滤电池条码为 0 或 "0" 或者未激活的电池active == 0
if ($battery_id === '0' || $battery_id === 0 || empty($battery_id) || $active == 0) {
continue;
}
$bkv_update_str = '';
foreach ($result_param_need as $p_val) {
// 结果参数
$p_param = $p_val['code'];
// 结果参数类型
$p_class = $p_val['field_type'];
// 结果参数值
$p_param_val = trim($param[$p_param][$battery_index]);
if (in_array($p_class, ['FLOAT', 'INT'])) {
$bkv_update_str .= "\"{$current_process_code}.{$p_param}\"={$p_param_val},";
} else {
$bkv_update_str .= "\"{$current_process_code}.{$p_param}\"='{$p_param_val}',";
}
}
if (!empty($bkv_update_str)) {
$bkv_update_str = $bkv_update_str . $common_update_str;
} else {
$bkv_update_str = $common_update_str;
}
$sql = sprintf(
"UPDATE \"%s\" SET %s WHERE battery_id='%s' AND tray='%s' AND lot='%s'",
config('app.bkv_prefix') . $subbatch,
$bkv_update_str,
$battery_id,
$tray,
$lot
);
$row = Db::query($sql);
if ($row === NULL) {
throw new Exception("PROCESS update failed:[tmp_bkv]");
}
// 获取battery_map的uuid与pid
// 判断如果查询不到battery_map的数据pid赋予-2uuid赋予空数组
$pid = '-2';
$uuid = json_encode([]);
$sql = sprintf(
"SELECT pid,uuid
FROM hf_mes_production_battery_map
WHERE battery_id='%s' ORDER BY id DESC LIMIT 1;",
$battery_id
);
$battery_map_ret = Db::fetch($sql);
if (!empty($battery_map_ret)) {
$pid = !empty($battery_map_ret['pid']) ? $battery_map_ret['pid'] : $pid;
$uuid = !empty($battery_map_ret['uuid']) ? $battery_map_ret['uuid'] : $uuid;
}
$forward_tracing_uuid = [];
//读取这个电池在process_log表中最新一条记录的forward_tracing_uuid如果有的话没有的话则赋值uuid
$sql = "SELECT forward_tracing_uuid
FROM hf_mes_bkv_batch_process_log
WHERE item_id = '" . $battery_id . "'
ORDER BY id DESC
LIMIT 1";
$ret = Db::fetch($sql);
if (!empty($ret)) {
$forward_tracing_uuid = $ret['forward_tracing_uuid'];
}
// 组装process_log新增数据
array_push($insert_process_log_data, [
'item_id' => $battery_id,
'batch' => $batch,
'subbatch' => $subbatch,
'tray' => $tray,
'lot' => $lot,
'process_code' => $current_process_code,
'workingsubclass' => $workingsubclass,
'device_code' => $device_code,
'channel' => $param['CHANNEL'][$battery_index],
'finish_time' => $param['FINISH_TIME'][$battery_index],
'input_finish_time' => $param['FINISH_TIME'][$battery_index],
'ng_code' => $param['NG'][$battery_index],
'status' => -1,
'uuid' => $uuid,
'pid' => $pid,
'last_status' => 1,
'forward_tracing_uuid' => $forward_tracing_uuid ?: $uuid
]);
}
// 修改tray_map表的date_log
foreach ($date_log as $k => $v) {
if ($v['flow_process_code'] == $current_process_code) {
$date_log[$k]['endTime'] = $param['FINISH_TIME'][0];
$date_log[$k]['device_code'] = $param['DEVICE_CODE'][0];
break;
}
}
// 修改tray_map表的date_log与active、next_process_code
$tray_map_update = [
'date_log' => json_encode($date_log, JSON_UNESCAPED_UNICODE),
'process_code' => $current_process_code,
'process_idx' => $current_process_idx,
'next_process_code' => $next_next_process_code
];
// 判断是否是最后一个工序, 追加取消托盘未激活状态修改
if ($next_next_process_code == -1) {
$tray_map_update['active'] = 0;
}
$row = Db::update(
'hf_mes_production_tray_map',
$tray_map_update,
[
'tray' => $tray,
'lot' => $lot,
'batch' => $batch,
'subbatch' => $subbatch,
'active' => 1
]
);
if ($row === NULL) {
throw new Exception("Record Update failed:[tray_map]");
}
// 写入process_log的数据(同步)
Event::emit('SetProcessLogEvent.handle', $insert_process_log_data);
// 写入pin_check数据(数据库队列缓存数据,异步处理)
if ($pin_check) {
Event::emit('SetTrayProcessResultEvent.setPincheckQueue', [
'param' => $param,
'device_code' => $device_code,
'batch' => $batch,
'subbatch' => $subbatch,
'tray' => $tray,
'lot' => $lot
]);
}
// 写入曲线数据(数据库队列缓存数据,异步处理)
if (in_array($workingsubclass, ['IC', 'YC', 'PRESSURE_FORMATION', 'HC'])) {
Event::emit('SetTrayProcessResultEvent.setCurveQueue', [
'param' => $param,
'device_code' => $device_code,
'batch' => $batch,
'subbatch' => $subbatch,
'tray' => $tray,
'lot' => $lot,
'process_code' => $current_process_code,
'battery_ids' => $bkv_battery_ids
]);
}
// 写入分档数据(数据库队列缓存数据,异步处理)
if (in_array($workingsubclass, ['IC'])) {
Event::emit('SetTrayProcessResultEvent.setGradingQueue', [
'param' => $param,
'batch' => $batch,
'subbatch' => $subbatch,
'tray' => $tray,
'lot' => $lot,
'process_code' => $current_process_code
]);
}
// 结果参数转发到scada(异步)
Event::emit('SendProcessResultParamsToScadaEvent.handle', ["workingsubclass" => $workingsubclass, "device_code" => $device_code, "param" => $post['param'], "batch" => $batch]);
// 写入K值数据(数据库队列缓存数据,异步处理)
// if (in_array($workingsubclass, ['OCV02'])) {
// Event::emit('SetTrayProcessResultEvent.setKQueue', [
// 'param' => $param,
// 'batch' => $batch,
// 'subbatch' => $subbatch,
// 'tray' => $tray,
// 'lot' => $lot,
// 'flow_id' => $flow_id
// ]);
// }
// 容量预测(数据库队列缓存数据,异步处理)
// if (in_array($workingsubclass, ['IC', 'PRESSURE_FORMATION', 'HC'])) {
// Event::emit('SetTrayProcessResultEvent.setKunQueue', [
// 'param' => $param,
// 'batch' => $batch,
// 'subbatch' => $subbatch,
// 'tray' => $tray,
// 'lot' => $lot,
// 'workingsubclass' => $workingsubclass
// ]);
// }
} catch (Exception $e) {
Db::rollBackTrans();
throw new Exception($e->getMessage());
}
Db::commitTrans();
return '';
}
}