392 lines
17 KiB
PHP
392 lines
17 KiB
PHP
|
<?php
|
|||
|
|
|||
|
namespace app\action;
|
|||
|
|
|||
|
use Exception;
|
|||
|
use libs\db\Db;
|
|||
|
use libs\listener\Event;
|
|||
|
|
|||
|
class SetBatteryProcessResult
|
|||
|
{
|
|||
|
public function execute($post)
|
|||
|
{
|
|||
|
// 验证数据
|
|||
|
$param = check_valid($post['action'], [
|
|||
|
['battery_ids', 'array', '电池条码数据'],
|
|||
|
['workingsubclass', 'string', '工序单元'],
|
|||
|
['device_code', 'string', '设备编码']
|
|||
|
], $post['param']);
|
|||
|
|
|||
|
$date = date('Y-m-d H:i:s');
|
|||
|
$param['DEVICE_CODE'] = [];
|
|||
|
$param['FINISH_TIME'] = [];
|
|||
|
|
|||
|
list($battery_ids, $workingsubclass, $device_code) = [
|
|||
|
$param['battery_ids'],
|
|||
|
$param['workingsubclass'],
|
|||
|
$param['device_code'],
|
|||
|
|
|||
|
];
|
|||
|
|
|||
|
try {
|
|||
|
// 判断上传上来的device_code是否存在
|
|||
|
$sql = sprintf(
|
|||
|
"SELECT device_category_id,code,name
|
|||
|
FROM hf_mes_device
|
|||
|
WHERE code='%s' LIMIT 1;",
|
|||
|
$device_code
|
|||
|
);
|
|||
|
|
|||
|
$ret = Db::fetch($sql);
|
|||
|
if (empty($ret)) {
|
|||
|
throw new Exception("设备编码[{$device_code}]不存在,请检查");
|
|||
|
}
|
|||
|
$device_category_id = $ret['device_category_id'];
|
|||
|
list($first_batch, $check_battery_ids) = ['', array()];
|
|||
|
|
|||
|
foreach ($battery_ids as $key => $battery_id) {
|
|||
|
// 判断电池是否为空
|
|||
|
if (empty($battery_id)) {
|
|||
|
throw new Exception("电池条码数组第[{$key}]位置的电池条码不能是:[0, '0', '', null, NAN]等,请上传电池条码", 4006);
|
|||
|
}
|
|||
|
// 判断如果查询不到battery_map的数据,pid赋予-2,uuid赋予空数组
|
|||
|
$pid = '-2';
|
|||
|
$uuid = json_encode([]);
|
|||
|
|
|||
|
// 判断是否存在battery_map中
|
|||
|
$sql = sprintf(
|
|||
|
"SELECT batch,tray,lot,subbatch,pid,uuid
|
|||
|
FROM hf_mes_production_battery_map
|
|||
|
WHERE battery_id='%s' ORDER BY id DESC LIMIT 1;",
|
|||
|
$battery_id
|
|||
|
);
|
|||
|
$ret = Db::fetch($sql);
|
|||
|
if (empty($ret)) {
|
|||
|
$key += 1;
|
|||
|
throw new Exception("电池数组[battery_ids]第[{$key}]位置的电池[{$battery_id}]数据不存在系统中,请检查");
|
|||
|
}
|
|||
|
$pid = !empty($ret['pid']) ? $ret['pid'] : $pid;
|
|||
|
$uuid = !empty($ret['uuid']) ? $ret['uuid'] : $uuid;
|
|||
|
|
|||
|
list($old_batch, $old_tray, $old_lot, $old_subbatch) = [
|
|||
|
$ret['batch'],
|
|||
|
$ret['tray'],
|
|||
|
$ret['lot'],
|
|||
|
$ret['subbatch']
|
|||
|
];
|
|||
|
if ($key == 0) {
|
|||
|
$first_batch = $old_subbatch;
|
|||
|
}
|
|||
|
|
|||
|
// 确认电池在之前托盘是激活状态
|
|||
|
$sql = sprintf(
|
|||
|
"SELECT next_process_code
|
|||
|
FROM \"%s\"
|
|||
|
WHERE battery_id='%s' AND tray='%s' AND lot='%s' AND active=1 LIMIT 1;",
|
|||
|
'hf_mes_tmp_bkv_' . $old_subbatch,
|
|||
|
$battery_id,
|
|||
|
$old_tray,
|
|||
|
$old_lot
|
|||
|
);
|
|||
|
$ret = Db::fetch($sql);
|
|||
|
if (empty($ret)) {
|
|||
|
$key += 1;
|
|||
|
throw new Exception("电池数组[battery_ids]第[{$key}]位置的电池[{$battery_id}]在原托盘[{$old_tray}]中不是激活状态,请检查");
|
|||
|
}
|
|||
|
$next_process_code = $ret['next_process_code'];
|
|||
|
|
|||
|
// 所有录入的电池的批次必须是一样的
|
|||
|
if ($first_batch != $old_subbatch) {
|
|||
|
$key += 1;
|
|||
|
throw new Exception("电池数组[battery_ids]第[{$key}]位置的电池[{$battery_id}]与第一个电池的批次不一致,请检查");
|
|||
|
}
|
|||
|
|
|||
|
array_push($check_battery_ids, [
|
|||
|
'battery_id' => $battery_id,
|
|||
|
'tray' => $old_tray,
|
|||
|
'lot' => $old_lot,
|
|||
|
'next_process_code' => $next_process_code,
|
|||
|
'pid' => $pid,
|
|||
|
'uuid' => $uuid,
|
|||
|
]);
|
|||
|
}
|
|||
|
|
|||
|
// 判断所有电池的工序是否一致
|
|||
|
$sql = sprintf(
|
|||
|
"SELECT flow_id
|
|||
|
FROM hf_mes_production_planning_management_subbatch
|
|||
|
WHERE subbatch='%s' LIMIT 1;",
|
|||
|
$first_batch
|
|||
|
);
|
|||
|
$ret = Db::fetch($sql);
|
|||
|
|
|||
|
$flow_id = $ret['flow_id'];
|
|||
|
$current_process_code = "{$flow_id}_{$workingsubclass}";
|
|||
|
|
|||
|
// 验证所有电池的当前工序编码是否与当前的工序一致
|
|||
|
foreach ($check_battery_ids as $item) {
|
|||
|
if ($item['next_process_code'] != $current_process_code) {
|
|||
|
throw new Exception("电池[{$item['battery_id']}]当前工序编码[{$item['next_process_code']}]与当前上传数据要求的设备工序编码[{$current_process_code}]不一致,请检查!");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 判断结果参数是否都上传了
|
|||
|
$sql = sprintf(
|
|||
|
"SELECT a.id,b.process
|
|||
|
FROM hf_mes_technology_process AS a
|
|||
|
INNER JOIN hf_mes_technology_flow b ON b.id = a.flow_id
|
|||
|
WHERE a.code='%s' LIMIT 1;",
|
|||
|
$current_process_code
|
|||
|
);
|
|||
|
$ret = Db::fetch($sql);
|
|||
|
|
|||
|
list($flow_process, $process_id) = [
|
|||
|
json_decode($ret['process'], true),
|
|||
|
$ret['id']
|
|||
|
];
|
|||
|
|
|||
|
// 根据电池数组赋予通道数据
|
|||
|
$param['CHANNEL'] = array_map(function ($value) {
|
|||
|
return $value + 1;
|
|||
|
}, array_keys($battery_ids));
|
|||
|
// 赋予设备结果参数数组
|
|||
|
$param['DEVICE_CODE'] = array_pad($param['DEVICE_CODE'], count($battery_ids), $device_code);
|
|||
|
// 赋予完成时间结果参数数组
|
|||
|
$param['FINISH_TIME'] = array_pad($param['FINISH_TIME'], count($battery_ids), $date);
|
|||
|
|
|||
|
// 刷选出需要设备上传的结果参数
|
|||
|
$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');
|
|||
|
|
|||
|
// 验证提交的结果数据
|
|||
|
// 1、验证是否上传了结果参数
|
|||
|
$diff = array_diff($result_param_need_params, array_keys($param));
|
|||
|
if (!empty($diff)) {
|
|||
|
throw new Exception("结果参数:[{" . implode(',', $diff) . "}]没有上传");
|
|||
|
}
|
|||
|
// 1、验证结果参数是否是数组格式
|
|||
|
// 2、验证结果参数的数组长度是否与电池数量一致
|
|||
|
// 3、验证具体的结果数据有没有上传与数据的类型
|
|||
|
foreach ($result_param_need as $item) {
|
|||
|
// 1、验证结果参数是否是数组格式
|
|||
|
if (!is_array($param[$item['code']])) {
|
|||
|
throw new Exception("上传的结果参数[{$item['code']}] 需要是数组!结果数据均为数组格式,请检查!");
|
|||
|
}
|
|||
|
// 1、验证结果参数的数组长度是否与电池数量一致
|
|||
|
if (count($param[$item['code']]) != count($battery_ids)) {
|
|||
|
$count = count($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]
|
|||
|
);
|
|||
|
|
|||
|
// 判断是否有下一工序
|
|||
|
$current_process_idx = -1;
|
|||
|
$next_next_process_code = '-1';
|
|||
|
$flow_process_column = array_column($flow_process, null, '2');
|
|||
|
if ($flow_process_column[$current_process_code][0] < (count($flow_process) - 1)) {
|
|||
|
$next_next_process_code = $flow_process[$flow_process_column[$current_process_code][0] + 1][2];
|
|||
|
} elseif ($flow_process_column[$current_process_code][0] == (count($flow_process) - 1)) {
|
|||
|
$next_next_process_code = '-1';
|
|||
|
} else {
|
|||
|
$next_next_process_code = '-1';
|
|||
|
}
|
|||
|
$current_process_idx = $flow_process_column[$current_process_code][0];
|
|||
|
|
|||
|
} catch (Exception $e) {
|
|||
|
throw new Exception($e->getMessage());
|
|||
|
}
|
|||
|
|
|||
|
// 开启事务
|
|||
|
Db::beginTrans();
|
|||
|
|
|||
|
try {
|
|||
|
// 标记最后一条数据的状态
|
|||
|
Event::emit('SetProcessLogEvent.updateLastStatus', $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 ($check_battery_ids as $battery_index => $val) {
|
|||
|
// 过滤0的数据
|
|||
|
if ($val['battery_id'] === '0') {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
$bkv_update_str = '';
|
|||
|
$ng_code = '';
|
|||
|
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}',";
|
|||
|
}
|
|||
|
|
|||
|
// 判断NG是否存在
|
|||
|
if ($p_param == 'NG') {
|
|||
|
if ($p_param_val != '') {
|
|||
|
$ng_code = $p_param_val;
|
|||
|
} else {
|
|||
|
$ng_code = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
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') . $first_batch,
|
|||
|
$bkv_update_str,
|
|||
|
$val['battery_id'],
|
|||
|
$val['tray'],
|
|||
|
$val['lot']
|
|||
|
);
|
|||
|
$row = Db::query($sql);
|
|||
|
if ($row === NULL) {
|
|||
|
throw new Exception("PROCESS update failed:[tmp_bkv]");
|
|||
|
}
|
|||
|
$forward_tracing_uuid = [];
|
|||
|
//读取这个电池在process_log表中最新一条记录的forward_tracing_uuid,如果有的话没有的话则赋值uuid
|
|||
|
$sql = "SELECT forward_tracing_uuid
|
|||
|
FROM hf_mes_bkv_batch_process_log
|
|||
|
WHERE item_id = '" . $val['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' => $val['battery_id'],
|
|||
|
'batch' => $old_batch,
|
|||
|
'subbatch' => $first_batch,
|
|||
|
'tray' => $val['tray'],
|
|||
|
'lot' => $val['lot'],
|
|||
|
'process_code' => $current_process_code,
|
|||
|
'workingsubclass' => $workingsubclass,
|
|||
|
'device_code' => $device_code,
|
|||
|
'device_category_id' => $device_category_id,
|
|||
|
'channel' => $param['CHANNEL'][$battery_index],
|
|||
|
'finish_time' => $param['FINISH_TIME'][$battery_index],
|
|||
|
'input_finish_time' => $param['FINISH_TIME'][$battery_index],
|
|||
|
'status' => -1,
|
|||
|
'pid' => $val['pid'],
|
|||
|
'uuid' => $val['uuid'],
|
|||
|
'last_status' => 1,
|
|||
|
'ng_code' => $ng_code ? $ng_code : 0,
|
|||
|
'class' => $ng_code ? 'NG' : null,
|
|||
|
'forward_tracing_uuid' => $forward_tracing_uuid ?: $val['uuid']
|
|||
|
]);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// 写入process_log的数据(同步)
|
|||
|
Event::emit('SetProcessLogEvent.handle', $insert_process_log_data);
|
|||
|
|
|||
|
// 写入曲线数据(同步)
|
|||
|
Event::emit('CurveDataPathEvent.handle', ["end_time" => isset($param["end_time"]) ? $param["end_time"] : "", "workingsubclass" => $workingsubclass, "data" => $insert_process_log_data]);
|
|||
|
|
|||
|
// 结果参数转发到scada(异步)
|
|||
|
Event::emit('SendProcessResultParamsToScadaEvent.handle', ["workingsubclass" => $workingsubclass, "device_code" => $device_code, "param" => $post['param'], "batch" => $old_batch]);
|
|||
|
|
|||
|
} catch (Exception $e) {
|
|||
|
Db::rollBackTrans();
|
|||
|
throw new Exception($e->getMessage());
|
|||
|
}
|
|||
|
Db::commitTrans();
|
|||
|
$data['process_code'] = $current_process_code;
|
|||
|
$data['class_name'] = get_class($this);
|
|||
|
$data['log_data'] = $insert_process_log_data;
|
|||
|
try {
|
|||
|
// 写入process_log的数据(同步)
|
|||
|
$response = Event::emit('ExtScriptEvent.extScriptEnd', $data);
|
|||
|
if ($response['ext_script_code'] != 0) {
|
|||
|
throw new Exception($response['ext_script_msg']);
|
|||
|
}
|
|||
|
|
|||
|
} catch (Exception $e) {
|
|||
|
throw new Exception($e->getMessage());
|
|||
|
}
|
|||
|
return '';
|
|||
|
}
|
|||
|
}
|