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 '';
|
||
}
|
||
}
|