443 lines
19 KiB
PHP
443 lines
19 KiB
PHP
|
<?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赋予-2,uuid赋予空数组
|
|||
|
$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 '';
|
|||
|
}
|
|||
|
}
|